mirror of
https://github.com/perstarkse/minne.git
synced 2026-04-25 18:28:44 +02:00
refactor: extendable templates
refactor: simplification refactor: simplification
This commit is contained in:
@@ -29,15 +29,17 @@ impl HtmlState {
|
||||
config: AppConfig,
|
||||
reranker_pool: Option<Arc<RerankerPool>>,
|
||||
embedding_provider: Arc<EmbeddingProvider>,
|
||||
template_engine: Option<Arc<TemplateEngine>>,
|
||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let template_engine = create_template_engine!("templates");
|
||||
debug!("Template engine created for html_router.");
|
||||
let templates =
|
||||
template_engine.unwrap_or_else(|| Arc::new(create_template_engine!("templates")));
|
||||
debug!("Template engine configured for html_router.");
|
||||
|
||||
Ok(Self {
|
||||
db,
|
||||
openai_client,
|
||||
session_store,
|
||||
templates: Arc::new(template_engine),
|
||||
templates,
|
||||
config,
|
||||
storage,
|
||||
reranker_pool,
|
||||
|
||||
20
html-router/templates/admin/_base.html
Normal file
20
html-router/templates/admin/_base.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{% extends 'admin/_layout.html' %}
|
||||
|
||||
{% block admin_navigation %}
|
||||
<a href="/admin?section=overview"
|
||||
class="nb-btn btn-sm px-4 {% if current_section == 'overview' %}nb-cta{% else %}btn-ghost{% endif %}">
|
||||
Overview
|
||||
</a>
|
||||
<a href="/admin?section=models"
|
||||
class="nb-btn btn-sm px-4 {% if current_section == 'models' %}nb-cta{% else %}btn-ghost{% endif %}">
|
||||
Models
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% if current_section == 'models' %}
|
||||
{% include 'admin/sections/models.html' %}
|
||||
{% else %}
|
||||
{% include 'admin/sections/overview.html' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
29
html-router/templates/admin/_layout.html
Normal file
29
html-router/templates/admin/_layout.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Admin{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id="admin-shell" class="flex justify-center grow mt-2 sm:mt-4 pb-4">
|
||||
<div class="container flex flex-col gap-4">
|
||||
<section class="nb-panel p-4 sm:p-5 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Admin Controls</h1>
|
||||
</div>
|
||||
<div class="text-xs opacity-60 sm:text-right">
|
||||
Signed in as <span class="font-medium">{{ user.email }}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<nav class="nb-panel p-2 flex flex-wrap gap-2 text-sm" hx-boost="true" hx-target="#admin-shell"
|
||||
hx-select="#admin-shell" hx-swap="outerHTML" hx-push-url="true">
|
||||
{% block admin_navigation %}
|
||||
{% endblock %}
|
||||
</nav>
|
||||
|
||||
<div id="admin-content" class="flex flex-col gap-4">
|
||||
{% block admin_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,38 +1 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Admin{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id="admin-shell" class="flex justify-center grow mt-2 sm:mt-4 pb-4">
|
||||
<div class="container flex flex-col gap-4">
|
||||
<section class="nb-panel p-4 sm:p-5 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Admin Controls</h1>
|
||||
</div>
|
||||
<div class="text-xs opacity-60 sm:text-right">
|
||||
Signed in as <span class="font-medium">{{ user.email }}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<nav class="nb-panel p-2 flex flex-wrap gap-2 text-sm" hx-boost="true" hx-target="#admin-shell"
|
||||
hx-select="#admin-shell" hx-swap="outerHTML" hx-push-url="true">
|
||||
<a href="/admin?section=overview"
|
||||
class="nb-btn btn-sm px-4 {% if current_section == 'overview' %}nb-cta{% else %}btn-ghost{% endif %}">
|
||||
Overview
|
||||
</a>
|
||||
<a href="/admin?section=models"
|
||||
class="nb-btn btn-sm px-4 {% if current_section == 'models' %}nb-cta{% else %}btn-ghost{% endif %}">
|
||||
Models
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div id="admin-content" class="flex flex-col gap-4">
|
||||
{% if current_section == 'models' %}
|
||||
{% include 'admin/sections/models.html' %}
|
||||
{% else %}
|
||||
{% include 'admin/sections/overview.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% extends "admin/_base.html" %}
|
||||
|
||||
72
html-router/templates/auth/_account_settings_core.html
Normal file
72
html-router/templates/auth/_account_settings_core.html
Normal file
@@ -0,0 +1,72 @@
|
||||
{% extends "auth/_settings_layout.html" %}
|
||||
|
||||
{% block settings_header %}
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Account Settings</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block settings_left_column %}
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">Email</div>
|
||||
<input type="email" name="email" value="{{ user.email }}" class="nb-input w-full" disabled />
|
||||
</label>
|
||||
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">API Key</div>
|
||||
{% block api_key_section %}
|
||||
{% if user.api_key %}
|
||||
<div class="relative">
|
||||
<input id="api_key_input" type="text" name="api_key" value="{{ user.api_key }}"
|
||||
class="nb-input w-full pr-14" disabled />
|
||||
<button type="button" id="copy_api_key_btn" onclick="copy_api_key()"
|
||||
class="absolute inset-y-0 right-0 flex items-center px-2 nb-btn btn-sm" aria-label="Copy API key"
|
||||
title="Copy API key">
|
||||
{% include "icons/clipboard_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
<a href="https://www.icloud.com/shortcuts/66985f7b98a74aaeac6ba29c3f1f0960"
|
||||
class="nb-btn nb-cta mt-2 w-full">Download iOS shortcut</a>
|
||||
{% else %}
|
||||
<button hx-post="/set-api-key" class="nb-btn nb-cta w-full" hx-swap="outerHTML">Create API-Key</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</label>
|
||||
|
||||
<script>
|
||||
function copy_api_key() {
|
||||
const input = document.getElementById('api_key_input');
|
||||
if (!input) return;
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(input.value)
|
||||
.then(() => show_toast('API key copied!', 'success'))
|
||||
.catch(() => show_toast('Copy failed', 'error'));
|
||||
} else {
|
||||
show_toast('Copy not supported', 'info');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">Timezone</div>
|
||||
{% block timezone_section %}
|
||||
<select name="timezone" class="nb-select w-full" hx-patch="/update-timezone" hx-swap="outerHTML">
|
||||
{% for tz in timezones %}
|
||||
<option value="{{ tz }}" {% if tz==user.timezone %}selected{% endif %}>{{ tz }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endblock %}
|
||||
</label>
|
||||
{% endblock %}
|
||||
|
||||
{% block settings_right_column %}
|
||||
<div>
|
||||
{% block change_password_section %}
|
||||
<button hx-get="/change-password" hx-swap="outerHTML" class="nb-btn w-full">Change Password</button>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button hx-delete="/delete-account"
|
||||
hx-confirm="This action will permanently delete your account and all data associated. Are you sure you want to continue?"
|
||||
class="nb-btn btn-error w-full">Delete Account</button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
10
html-router/templates/auth/_layout.html
Normal file
10
html-router/templates/auth/_layout.html
Normal file
@@ -0,0 +1,10 @@
|
||||
{% extends "head_base.html" %}
|
||||
|
||||
{% block title %}Minne - Auth{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="min-h-[100dvh] flex flex-col items-center justify-center">
|
||||
{% block auth_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
32
html-router/templates/auth/_settings_layout.html
Normal file
32
html-router/templates/auth/_settings_layout.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{% extends "body_base.html" %}
|
||||
|
||||
{% block title %}Minne - Account{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4 pb-4">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block settings_header %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid-cols-1 lg:grid-cols-2 gap-4 space-y-2">
|
||||
<!-- Left column -->
|
||||
<div class="nb-panel p-4 space-y-2 flex flex-col">
|
||||
{% block settings_left_column %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<!-- Right column -->
|
||||
<div class="nb-panel p-4 space-y-2">
|
||||
{% block settings_right_column %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="account-result" class="mt-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,88 +1 @@
|
||||
{% extends "body_base.html" %}
|
||||
|
||||
{% block title %}Minne - Account{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4 pb-4">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Account Settings</h1>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid-cols-1 lg:grid-cols-2 gap-4 space-y-2">
|
||||
<!-- Left column -->
|
||||
<div class="nb-panel p-4 space-y-2 flex flex-col">
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">Email</div>
|
||||
<input type="email" name="email" value="{{ user.email }}" class="nb-input w-full" disabled />
|
||||
</label>
|
||||
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">API Key</div>
|
||||
{% block api_key_section %}
|
||||
{% if user.api_key %}
|
||||
<div class="relative">
|
||||
<input id="api_key_input" type="text" name="api_key" value="{{ user.api_key }}"
|
||||
class="nb-input w-full pr-14" disabled />
|
||||
<button type="button" id="copy_api_key_btn" onclick="copy_api_key()"
|
||||
class="absolute inset-y-0 right-0 flex items-center px-2 nb-btn btn-sm" aria-label="Copy API key"
|
||||
title="Copy API key">
|
||||
{% include "icons/clipboard_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
<a href="https://www.icloud.com/shortcuts/66985f7b98a74aaeac6ba29c3f1f0960"
|
||||
class="nb-btn nb-cta mt-2 w-full">Download iOS shortcut</a>
|
||||
{% else %}
|
||||
<button hx-post="/set-api-key" class="nb-btn nb-cta w-full" hx-swap="outerHTML">Create API-Key</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</label>
|
||||
|
||||
<script>
|
||||
function copy_api_key() {
|
||||
const input = document.getElementById('api_key_input');
|
||||
if (!input) return;
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(input.value)
|
||||
.then(() => show_toast('API key copied!', 'success'))
|
||||
.catch(() => show_toast('Copy failed', 'error'));
|
||||
} else {
|
||||
show_toast('Copy not supported', 'info');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<label class="w-full">
|
||||
<div class="text-xs uppercase tracking-wide opacity-70 mb-1">Timezone</div>
|
||||
{% block timezone_section %}
|
||||
<select name="timezone" class="nb-select w-full" hx-patch="/update-timezone" hx-swap="outerHTML">
|
||||
{% for tz in timezones %}
|
||||
<option value="{{ tz }}" {% if tz==user.timezone %}selected{% endif %}>{{ tz }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endblock %}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Right column -->
|
||||
<div class="nb-panel p-4 space-y-2">
|
||||
<div>
|
||||
{% block change_password_section %}
|
||||
<button hx-get="/change-password" hx-swap="outerHTML" class="nb-btn w-full">Change Password</button>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button hx-delete="/delete-account"
|
||||
hx-confirm="This action will permanently delete your account and all data associated. Are you sure you want to continue?"
|
||||
class="nb-btn btn-error w-full">Delete Account</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="account-result" class="mt-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% extends "auth/_account_settings_core.html" %}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
{% extends "head_base.html" %}
|
||||
{% extends "auth/_layout.html" %}
|
||||
|
||||
{% block title %}Minne - Sign in{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="min-h-[100dvh] flex">
|
||||
{% block auth_content %}
|
||||
{% include "auth/signin_form.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,9 +1,8 @@
|
||||
{% extends "head_base.html" %}
|
||||
{% extends "auth/_layout.html" %}
|
||||
|
||||
{% block title %}Minne - Sign up{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="min-h-[100dvh] flex items-center">
|
||||
{% block auth_content %}
|
||||
<div class="container mx-auto px-4 sm:max-w-md">
|
||||
<div class="nb-card p-5">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
@@ -46,10 +45,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
<script>
|
||||
// Detect timezone and set hidden input
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
document.getElementById("timezone").value = timezone;
|
||||
</script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
78
html-router/templates/chat/_layout.html
Normal file
78
html-router/templates/chat/_layout.html
Normal file
@@ -0,0 +1,78 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Chat{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex grow relative justify-center mt-2 sm:mt-4">
|
||||
<div class="container">
|
||||
<section class="mb-3">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block chat_header_actions %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
<div id="chat-scroll-container" class="overflow-auto hide-scrollbar">
|
||||
{% block chat_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function doScrollChatToBottom() {
|
||||
const mainScroll = document.querySelector('main');
|
||||
if (mainScroll) mainScroll.scrollTop = mainScroll.scrollHeight;
|
||||
|
||||
const chatScroll = document.getElementById('chat-scroll-container');
|
||||
if (chatScroll) chatScroll.scrollTop = chatScroll.scrollHeight;
|
||||
|
||||
const chatContainer = document.getElementById('chat_container');
|
||||
if (chatContainer) chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
}
|
||||
|
||||
function scrollChatToBottom() {
|
||||
if (!window.location.pathname.startsWith('/chat')) return;
|
||||
requestAnimationFrame(doScrollChatToBottom);
|
||||
}
|
||||
|
||||
window.scrollChatToBottom = scrollChatToBottom;
|
||||
|
||||
// Delay initial scroll to avoid interfering with view transition
|
||||
document.addEventListener('DOMContentLoaded', () => setTimeout(scrollChatToBottom, 350));
|
||||
|
||||
function handleChatSwap(e) {
|
||||
if (!window.location.pathname.startsWith('/chat')) return;
|
||||
// Full page swap: delay for view transition; partial swap: immediate
|
||||
if (e.detail && e.detail.target && e.detail.target.tagName === 'BODY') {
|
||||
setTimeout(scrollChatToBottom, 350);
|
||||
} else {
|
||||
scrollChatToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupChatListeners(e) {
|
||||
if (e.detail && e.detail.target && e.detail.target.tagName === 'BODY') {
|
||||
document.body.removeEventListener('htmx:afterSwap', window._chatEventHandlers.afterSwap);
|
||||
document.body.removeEventListener('htmx:afterSettle', window._chatEventHandlers.afterSettle);
|
||||
document.body.removeEventListener('htmx:beforeSwap', window._chatEventHandlers.beforeSwap);
|
||||
delete window._chatEventHandlers;
|
||||
window._chatListenersAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
window._chatEventHandlers = {
|
||||
afterSwap: handleChatSwap,
|
||||
afterSettle: handleChatSwap,
|
||||
beforeSwap: cleanupChatListeners
|
||||
};
|
||||
|
||||
if (!window._chatListenersAttached) {
|
||||
document.body.addEventListener('htmx:afterSwap', window._chatEventHandlers.afterSwap);
|
||||
document.body.addEventListener('htmx:afterSettle', window._chatEventHandlers.afterSettle);
|
||||
document.body.addEventListener('htmx:beforeSwap', window._chatEventHandlers.beforeSwap);
|
||||
window._chatListenersAttached = true;
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,81 +1,14 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% extends "chat/_layout.html" %}
|
||||
|
||||
{% block title %}Minne - Chat{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex grow relative justify-center mt-2 sm:mt-4">
|
||||
<div class="container">
|
||||
<section class="mb-3">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block chat_header_actions %}
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Chat</h1>
|
||||
<div class="text-xs opacity-70">Converse with your knowledge</div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="chat-scroll-container" class="overflow-auto hide-scrollbar">
|
||||
{% endblock %}
|
||||
|
||||
{% block chat_content %}
|
||||
{% include "chat/history.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function doScrollChatToBottom() {
|
||||
const mainScroll = document.querySelector('main');
|
||||
if (mainScroll) mainScroll.scrollTop = mainScroll.scrollHeight;
|
||||
|
||||
const chatScroll = document.getElementById('chat-scroll-container');
|
||||
if (chatScroll) chatScroll.scrollTop = chatScroll.scrollHeight;
|
||||
|
||||
const chatContainer = document.getElementById('chat_container');
|
||||
if (chatContainer) chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
}
|
||||
|
||||
function scrollChatToBottom() {
|
||||
if (!window.location.pathname.startsWith('/chat')) return;
|
||||
requestAnimationFrame(doScrollChatToBottom);
|
||||
}
|
||||
|
||||
window.scrollChatToBottom = scrollChatToBottom;
|
||||
|
||||
// Delay initial scroll to avoid interfering with view transition
|
||||
document.addEventListener('DOMContentLoaded', () => setTimeout(scrollChatToBottom, 350));
|
||||
|
||||
function handleChatSwap(e) {
|
||||
if (!window.location.pathname.startsWith('/chat')) return;
|
||||
// Full page swap: delay for view transition; partial swap: immediate
|
||||
if (e.detail && e.detail.target && e.detail.target.tagName === 'BODY') {
|
||||
setTimeout(scrollChatToBottom, 350);
|
||||
} else {
|
||||
scrollChatToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupChatListeners(e) {
|
||||
if (e.detail && e.detail.target && e.detail.target.tagName === 'BODY') {
|
||||
document.body.removeEventListener('htmx:afterSwap', window._chatEventHandlers.afterSwap);
|
||||
document.body.removeEventListener('htmx:afterSettle', window._chatEventHandlers.afterSettle);
|
||||
document.body.removeEventListener('htmx:beforeSwap', window._chatEventHandlers.beforeSwap);
|
||||
delete window._chatEventHandlers;
|
||||
window._chatListenersAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
window._chatEventHandlers = {
|
||||
afterSwap: handleChatSwap,
|
||||
afterSettle: handleChatSwap,
|
||||
beforeSwap: cleanupChatListeners
|
||||
};
|
||||
|
||||
if (!window._chatListenersAttached) {
|
||||
document.body.addEventListener('htmx:afterSwap', window._chatEventHandlers.afterSwap);
|
||||
document.body.addEventListener('htmx:afterSettle', window._chatEventHandlers.afterSettle);
|
||||
document.body.addEventListener('htmx:beforeSwap', window._chatEventHandlers.beforeSwap);
|
||||
window._chatListenersAttached = true;
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block overlay %}
|
||||
{% include "chat/new_message_form.html" %}
|
||||
{% include "chat/new_message_form.html" %}
|
||||
{% endblock %}
|
||||
|
||||
15
html-router/templates/components/_icon_macro.html
Normal file
15
html-router/templates/components/_icon_macro.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% macro icon(name) %}
|
||||
{% if name == "home" %}
|
||||
{% include "icons/home_icon.html" %}
|
||||
{% elif name == "book" %}
|
||||
{% include "icons/book_icon.html" %}
|
||||
{% elif name == "document" %}
|
||||
{% include "icons/document_icon.html" %}
|
||||
{% elif name == "chat" %}
|
||||
{% include "icons/chat_icon.html" %}
|
||||
{% elif name == "search" %}
|
||||
{% include "icons/search_icon.html" %}
|
||||
{% elif name == "scratchpad" %}
|
||||
{% include "icons/scratchpad_icon.html" %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
14
html-router/templates/components/_navbar_layout.html
Normal file
14
html-router/templates/components/_navbar_layout.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<nav class="sticky top-0 z-10 nb-panel nb-panel-canvas border-t-0">
|
||||
<div class="container mx-auto navbar">
|
||||
<div class="mr-2 flex-1">
|
||||
{% block navbar_search %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
<ul class="menu menu-horizontal px-2 gap-2 items-center">
|
||||
{% block navbar_actions %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
60
html-router/templates/components/_sidebar_layout.html
Normal file
60
html-router/templates/components/_sidebar_layout.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<div class="drawer-side z-20">
|
||||
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
|
||||
|
||||
<ul class="menu p-0 w-72 h-full nb-canvas text-base-content flex flex-col border-r-2 border-neutral">
|
||||
<!-- === TOP FIXED SECTION === -->
|
||||
<div class="px-2 mt-4 space-y-3">
|
||||
{% block sidebar_nav_items %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<!-- === MIDDLE SCROLLABLE SECTION === -->
|
||||
<span class="px-4 py-2 nb-label">Recent Chats</span>
|
||||
<div class="flex-1 overflow-y-auto space-y-1 custom-scrollbar">
|
||||
{% if conversation_archive is defined and conversation_archive %}
|
||||
{% for conversation in conversation_archive %}
|
||||
<li id="conversation-{{ conversation.id }}">
|
||||
{% if edit_conversation_id == conversation.id %}
|
||||
<!-- Edit mode -->
|
||||
<form hx-patch="/chat/{{ conversation.id }}/title" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="flex items-center gap-1 px-2 py-2 max-w-72 relative">
|
||||
<input type="text" name="title" value="{{ conversation.title }}" class="nb-input nb-input-sm max-w-52" />
|
||||
<div class="flex gap-0.5 absolute right-2">
|
||||
<button type="submit" class="btn btn-ghost btn-xs !p-0">{% include "icons/check_icon.html" %}</button>
|
||||
<button type="button" hx-get="/chat/sidebar" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="btn btn-ghost btn-xs !p-0">
|
||||
{% include "icons/x_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<!-- View mode -->
|
||||
<div class="flex w-full pl-4 pr-2 py-2">
|
||||
<a hx-boost="true" href="/chat/{{ conversation.id }}" class="flex-grow text-sm truncate">
|
||||
<span>{{ conversation.title }}</span>
|
||||
</a>
|
||||
<div class="flex items-center gap-0.5 ml-2">
|
||||
<button hx-get="/chat/{{ conversation.id }}/title" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="btn btn-ghost btn-xs">
|
||||
{% include "icons/edit_icon.html" %}
|
||||
</button>
|
||||
<button hx-delete="/chat/{{ conversation.id }}" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to delete this chat?" class="btn btn-ghost btn-xs">
|
||||
{% include "icons/delete_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- === BOTTOM FIXED SECTION === -->
|
||||
<div class="px-2 pb-4 space-y-3">
|
||||
{% block sidebar_bottom_actions %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
17
html-router/templates/content/_layout.html
Normal file
17
html-router/templates/content/_layout.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Content{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<main id="main_section" class="flex justify-center grow mt-2 sm:mt-4 gap-6 mb-10 w-full">
|
||||
<div class="container">
|
||||
<div class="nb-panel p-3 mb-4 flex items-center justify-between">
|
||||
{% block content_header %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% block content_list %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,11 +1,6 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% extends 'content/_layout.html' %}
|
||||
|
||||
{% block title %}Minne - Content{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<main id="main_section" class="flex justify-center grow mt-2 sm:mt-4 gap-6 mb-10 w-full">
|
||||
<div class="container">
|
||||
<div class="nb-panel p-3 mb-4 flex items-center justify-between">
|
||||
{% block content_header %}
|
||||
<h2 class="text-xl font-extrabold tracking-tight">Content</h2>
|
||||
<form hx-get="/content" hx-target="#main_section" hx-swap="outerHTML" hx-push-url="true"
|
||||
class="flex items-center gap-2 mt-2 sm:mt-0">
|
||||
@@ -21,9 +16,8 @@
|
||||
</div>
|
||||
<button type="submit" class="nb-btn btn-sm">Filter</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% include "content/content_list.html" %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{% block content_list %}
|
||||
{% include "content/content_list.html" %}
|
||||
{% endblock %}
|
||||
|
||||
15
html-router/templates/dashboard/_base.html
Normal file
15
html-router/templates/dashboard/_base.html
Normal file
@@ -0,0 +1,15 @@
|
||||
{% extends "dashboard/_layout.html" %}
|
||||
|
||||
{% block dashboard_header %}
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Dashboard</h1>
|
||||
<button class="nb-btn nb-cta" hx-get="/ingress-form" hx-target="#modal" hx-swap="innerHTML">
|
||||
{% include "icons/send_icon.html" %}
|
||||
<span class="ml-2">Add Content</span>
|
||||
</button>
|
||||
{% endblock %}
|
||||
|
||||
{% block dashboard_widgets %}
|
||||
{% include "dashboard/statistics.html" %}
|
||||
{% include "dashboard/recent_content.html" %}
|
||||
{% include "dashboard/active_jobs.html" %}
|
||||
{% endblock %}
|
||||
21
html-router/templates/dashboard/_layout.html
Normal file
21
html-router/templates/dashboard/_layout.html
Normal file
@@ -0,0 +1,21 @@
|
||||
{% extends "body_base.html" %}
|
||||
|
||||
{% block title %}Minne - Dashboard{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4 pb-4 w-full">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
{% block dashboard_alerts %}
|
||||
{% endblock %}
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block dashboard_header %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% block dashboard_widgets %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,26 +1 @@
|
||||
{% extends "body_base.html" %}
|
||||
|
||||
{% block title %}Minne - Dashboard{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4 pb-4 w-full">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Dashboard</h1>
|
||||
<button class="nb-btn nb-cta" hx-get="/ingress-form" hx-target="#modal" hx-swap="innerHTML">
|
||||
{% include "icons/send_icon.html" %}
|
||||
<span class="ml-2">Add Content</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% include "dashboard/statistics.html" %}
|
||||
|
||||
{% include "dashboard/recent_content.html" %}
|
||||
|
||||
{% include "dashboard/active_jobs.html" %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% extends "dashboard/_base.html" %}
|
||||
|
||||
9
html-router/templates/errors/_layout.html
Normal file
9
html-router/templates/errors/_layout.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% block main %}
|
||||
<main class="container justify-center flex-grow flex mx-auto mt-4">
|
||||
<div class="flex flex-col space-y-4 text-center justify-center">
|
||||
{% block error_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -1,13 +1,10 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% block main %}
|
||||
<main class="container justify-center flex-grow flex mx-auto mt-4">
|
||||
<div class="flex flex-col space-y-4 text-center justify-center">
|
||||
{% extends "errors/_layout.html" %}
|
||||
|
||||
{% block error_content %}
|
||||
<h1 class="text-2xl font-bold text-error">
|
||||
{{ status_code }}
|
||||
</h1>
|
||||
<p class="text-2xl my-4">{{ title }}</p>
|
||||
<p class="text-base-content/60">{{ description }}</p>
|
||||
<a href="/" class="btn btn-primary mt-8">Go Home</a>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
17
html-router/templates/knowledge/_layout.html
Normal file
17
html-router/templates/knowledge/_layout.html
Normal file
@@ -0,0 +1,17 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Knowledge{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id="knowledge_pane" class="flex justify-center grow mt-2 sm:mt-4 gap-6">
|
||||
<div class="container">
|
||||
<div class="nb-panel p-3 mb-4 space-y-3 sm:space-y-0 sm:flex sm:flex-row sm:justify-between sm:items-center">
|
||||
{% block knowledge_header %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% block knowledge_content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,11 +1,6 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% extends 'knowledge/_layout.html' %}
|
||||
|
||||
{% block title %}Minne - Knowledge{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id="knowledge_pane" class="flex justify-center grow mt-2 sm:mt-4 gap-6">
|
||||
<div class="container">
|
||||
<div class="nb-panel p-3 mb-4 space-y-3 sm:space-y-0 sm:flex sm:flex-row sm:justify-between sm:items-center">
|
||||
{% block knowledge_header %}
|
||||
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
|
||||
<h2 class="text-xl font-extrabold tracking-tight">Knowledge Entities</h2>
|
||||
<button type="button" class="nb-btn nb-cta btn-sm mr-2" hx-get="/knowledge-entity/new" hx-target="#modal"
|
||||
@@ -35,8 +30,9 @@
|
||||
</div>
|
||||
<button type="submit" class="nb-btn btn-sm">Filter</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block knowledge_content %}
|
||||
<h2 class="text-2xl font-bold mb-2 mt-10 ">Graph</h2>
|
||||
<div class="nb-card mt-4 p-2">
|
||||
<div id="knowledge-graph" class="w-full" style="height: 640px;"
|
||||
@@ -47,6 +43,4 @@
|
||||
{% include "knowledge/entity_list.html" %}
|
||||
<h2 class="text-2xl font-bold mb-2 mt-2">Relationships</h2>
|
||||
{% include "knowledge/relationship_table.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,15 +1,12 @@
|
||||
<nav class="sticky top-0 z-10 nb-panel nb-panel-canvas border-t-0" style="view-transition-name: navbar; contain: layout;">
|
||||
<div class="container mx-auto navbar">
|
||||
<div class="mr-2 flex-1">
|
||||
{% extends "components/_navbar_layout.html" %}
|
||||
|
||||
{% block navbar_search %}
|
||||
{% include "searchbar.html" %}
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
<ul class="menu menu-horizontal px-2 gap-2 items-center">
|
||||
{% endblock %}
|
||||
|
||||
{% block navbar_actions %}
|
||||
<label for="my-drawer" aria-label="open sidebar" class="hover:cursor-pointer lg:hidden">
|
||||
{% include "icons/hamburger_icon.html" %}
|
||||
</label>
|
||||
{% include "theme_toggle.html" %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
|
||||
24
html-router/templates/scratchpad/_layout.html
Normal file
24
html-router/templates/scratchpad/_layout.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends 'body_base.html' %}
|
||||
|
||||
{% block title %}Minne - Scratchpad{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<main id="main_section" class="flex justify-center grow mt-2 sm:mt-4 gap-6 mb-10 w-full">
|
||||
<div class="container">
|
||||
{% block scratchpad_header %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scratchpad_content %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scratchpad_archived %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{% if new_scratchpad %}
|
||||
<div hx-swap-oob="innerHTML:#modal">
|
||||
<div hx-get="/scratchpad/{{ new_scratchpad.id }}/modal" hx-trigger="load" hx-target="#modal" hx-swap="innerHTML"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,11 +1,6 @@
|
||||
{% extends 'body_base.html' %}
|
||||
{% extends 'scratchpad/_layout.html' %}
|
||||
|
||||
{% block title %}Minne - Scratchpad{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<main id="main_section" class="flex justify-center grow mt-2 sm:mt-4 gap-6 mb-10 w-full">
|
||||
<div class="container">
|
||||
{% block header %}
|
||||
{% block scratchpad_header %}
|
||||
<div class="nb-panel p-3 mb-4 flex items-center justify-between">
|
||||
<h2 class="text-xl font-extrabold tracking-tight">Scratchpads</h2>
|
||||
<form hx-post="/scratchpad" hx-target="#main_section" hx-swap="outerHTML" class="flex gap-2">
|
||||
@@ -15,9 +10,9 @@
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block scratchpad_content %}
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{% for scratchpad in scratchpads %}
|
||||
<div class="nb-card p-4 hover:nb-shadow-hover transition-all">
|
||||
@@ -57,8 +52,9 @@
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block scratchpad_archived %}
|
||||
{% if archived_scratchpads %}
|
||||
<div class="mt-6">
|
||||
<details class="nb-panel p-3 space-y-4">
|
||||
@@ -102,12 +98,4 @@
|
||||
</details>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{% if new_scratchpad %}
|
||||
<div hx-swap-oob="innerHTML:#modal">
|
||||
<div hx-get="/scratchpad/{{ new_scratchpad.id }}/modal" hx-trigger="load" hx-target="#modal" hx-swap="innerHTML"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
18
html-router/templates/search/_layout.html
Normal file
18
html-router/templates/search/_layout.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% extends "body_base.html" %}
|
||||
|
||||
{% block title %}Minne - Search{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block search_header %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
{% block search_results %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,17 +1,10 @@
|
||||
{% extends "body_base.html" %}
|
||||
{% extends "search/_layout.html" %}
|
||||
|
||||
{% block title %}Minne - Search{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="flex justify-center grow mt-2 sm:mt-4">
|
||||
<div class="container">
|
||||
<section class="mb-4">
|
||||
<div class="nb-panel p-3 flex items-center justify-between">
|
||||
{% block search_header %}
|
||||
<h1 class="text-xl font-extrabold tracking-tight">Search</h1>
|
||||
<div class="text-xs opacity-70">Find documents, entities, and snippets</div>
|
||||
</div>
|
||||
</section>
|
||||
{% include "search/response.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block search_results %}
|
||||
{% include "search/response.html" %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
{% macro icon(name) %}
|
||||
{% if name == "home" %}
|
||||
{% include "icons/home_icon.html" %}
|
||||
{% elif name == "book" %}
|
||||
{% include "icons/book_icon.html" %}
|
||||
{% elif name == "document" %}
|
||||
{% include "icons/document_icon.html" %}
|
||||
{% elif name == "chat" %}
|
||||
{% include "icons/chat_icon.html" %}
|
||||
{% elif name == "search" %}
|
||||
{% include "icons/search_icon.html" %}
|
||||
{% elif name == "scratchpad" %}
|
||||
{% include "icons/scratchpad_icon.html" %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% extends "components/_sidebar_layout.html" %}
|
||||
{% from "components/_icon_macro.html" import icon %}
|
||||
|
||||
<div class="drawer-side z-20" style="view-transition-name: sidebar; contain: layout;">
|
||||
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
|
||||
|
||||
<ul class="menu p-0 w-72 h-full nb-canvas text-base-content flex flex-col border-r-2 border-neutral">
|
||||
<!-- <a class="px-4 py-4 text-2xl font-extrabold tracking-tight text-primary border-b-2 border-neutral bg-base-100 nb-shadow" -->
|
||||
<!-- href="/" hx-boost="true">Minne</a> -->
|
||||
|
||||
<!-- === TOP FIXED SECTION === -->
|
||||
<div class="px-2 mt-4 space-y-3">
|
||||
{% block sidebar_nav_items %}
|
||||
{% for url, name, label in [
|
||||
("/", "home", "Dashboard"),
|
||||
("/knowledge", "book", "Knowledge"),
|
||||
@@ -44,53 +23,9 @@
|
||||
Content</button>
|
||||
</li>
|
||||
<div class="u-hairline mt-4"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- === MIDDLE SCROLLABLE SECTION === -->
|
||||
<span class="px-4 py-2 nb-label">Recent Chats</span>
|
||||
<div class="flex-1 overflow-y-auto space-y-1 custom-scrollbar">
|
||||
{% if conversation_archive is defined and conversation_archive %}
|
||||
{% for conversation in conversation_archive %}
|
||||
<li id="conversation-{{ conversation.id }}">
|
||||
{% if edit_conversation_id == conversation.id %}
|
||||
<!-- Edit mode -->
|
||||
<form hx-patch="/chat/{{ conversation.id }}/title" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="flex items-center gap-1 px-2 py-2 max-w-72 relative">
|
||||
<input type="text" name="title" value="{{ conversation.title }}" class="nb-input nb-input-sm max-w-52" />
|
||||
<div class="flex gap-0.5 absolute right-2">
|
||||
<button type="submit" class="btn btn-ghost btn-xs !p-0">{% include "icons/check_icon.html" %}</button>
|
||||
<button type="button" hx-get="/chat/sidebar" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="btn btn-ghost btn-xs !p-0">
|
||||
{% include "icons/x_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<!-- View mode -->
|
||||
<div class="flex w-full pl-4 pr-2 py-2">
|
||||
<a hx-boost="true" href="/chat/{{ conversation.id }}" class="flex-grow text-sm truncate">
|
||||
<span>{{ conversation.title }}</span>
|
||||
</a>
|
||||
<div class="flex items-center gap-0.5 ml-2">
|
||||
<button hx-get="/chat/{{ conversation.id }}/title" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
class="btn btn-ghost btn-xs">
|
||||
{% include "icons/edit_icon.html" %}
|
||||
</button>
|
||||
<button hx-delete="/chat/{{ conversation.id }}" hx-target=".drawer-side" hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to delete this chat?" class="btn btn-ghost btn-xs">
|
||||
{% include "icons/delete_icon.html" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- === BOTTOM FIXED SECTION === -->
|
||||
<div class="px-2 pb-4 space-y-3">
|
||||
{% block sidebar_bottom_actions %}
|
||||
<li>
|
||||
<a hx-boost="true" href="/account"
|
||||
class="nb-btn w-full justify-start items-center gap-3 bg-base-100 hover:bg-base-200">
|
||||
@@ -114,6 +49,4 @@
|
||||
<span class="uppercase tracking-wide">Logout</span>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -116,6 +116,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
config.clone(),
|
||||
reranker_pool.clone(),
|
||||
embedding_provider.clone(),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -284,6 +285,7 @@ mod tests {
|
||||
config.clone(),
|
||||
None,
|
||||
embedding_provider,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("failed to build html state");
|
||||
|
||||
@@ -71,6 +71,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
config.clone(),
|
||||
reranker_pool,
|
||||
embedding_provider,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user