hero page, ingress form

This commit is contained in:
Per Stark
2024-12-30 23:57:13 +01:00
parent 981da5a649
commit a3bb73646c
17 changed files with 199 additions and 73 deletions

File diff suppressed because one or more lines are too long

View File

@@ -13,6 +13,7 @@
packages = [
pkgs.openssl
pkgs.nodejs
pkgs.vscode-langservers-extracted
];
# https://devenv.sh/languages/

View File

@@ -26,6 +26,7 @@ use zettle_db::{
html::{
account::{delete_account, set_api_key, show_account_page},
index::index_handler,
ingress::{process_ingress_form, show_ingress_form},
search_result::search_result_handler,
signin::{authenticate_user, show_signin_form},
signout::sign_out_user,
@@ -152,6 +153,10 @@ fn html_routes(
.route("/search", get(search_result_handler))
.route("/signout", get(sign_out_user))
.route("/signin", get(show_signin_form).post(authenticate_user))
.route(
"/ingress",
get(show_ingress_form).post(process_ingress_form),
)
.route("/account", get(show_account_page))
.route("/set-api-key", post(set_api_key))
.route("/delete-account", delete(delete_account))

View File

@@ -11,7 +11,7 @@ use crate::{
storage::types::user::User,
};
page_data!(IndexData, "index.html", {
page_data!(IndexData, "index/index.html", {
queue_length: u32,
user: Option<User>
});

View File

@@ -0,0 +1,71 @@
use axum::{
extract::State,
http::{StatusCode, Uri},
response::{Html, IntoResponse, Redirect},
Form,
};
use axum_htmx::{HxBoosted, HxRedirect};
use axum_session_auth::AuthSession;
use axum_session_surreal::SessionSurrealPool;
use axum_typed_multipart::{FieldData, TryFromMultipart, TypedMultipart};
use serde::{Deserialize, Serialize};
use surrealdb::{engine::any::Any, Surreal};
use tempfile::NamedTempFile;
use tracing::info;
use crate::{
error::ApiError,
server::AppState,
storage::types::{file_info::FileInfo, user::User},
};
use super::{render_block, render_template};
#[derive(Serialize)]
struct PageData {
// name: String,
}
pub async fn show_ingress_form(
State(state): State<AppState>,
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
) -> Result<impl IntoResponse, ApiError> {
if !auth.is_authenticated() {
return Ok(Redirect::to("/").into_response());
}
Ok(render_template("ingress_form.html", PageData {}, state.templates)?.into_response())
}
#[derive(Debug, TryFromMultipart)]
pub struct IngressParams {
pub content: Option<String>,
pub instructions: String,
pub category: String,
#[form_data(limit = "10000000")] // Adjust limit as needed
pub files: Vec<FieldData<NamedTempFile>>,
}
pub async fn process_ingress_form(
State(state): State<AppState>,
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
TypedMultipart(input): TypedMultipart<IngressParams>,
) -> Result<impl IntoResponse, ApiError> {
let user = match auth.current_user {
Some(user) => user,
None => return Ok(Redirect::to("/").into_response()),
};
info!("{:?}", input);
// Process files and create FileInfo objects
let mut file_infos = Vec::new();
for file in input.files {
let file_info = FileInfo::new(file, &state.surreal_db_client).await?;
file_infos.push(file_info);
}
// Process the ingress (implement your logic here)
Ok(Html("SuccessBRO!").into_response())
// Ok((HxRedirect::from(Uri::from_static("/")), StatusCode::OK).into_response())
}

View File

@@ -5,6 +5,7 @@ use minijinja_autoreload::AutoReloader;
pub mod account;
pub mod index;
pub mod ingress;
pub mod search_result;
pub mod signin;
pub mod signout;

View File

@@ -34,7 +34,7 @@ pub async fn search_result_handler(
)
.await?;
Ok(Html("Hello".to_string()))
Ok(Html(answer.content))
// let output = state
// .tera
// .render(

View File

@@ -6,7 +6,7 @@
}
</style>
<div class="min-h-screen container mx-auto max-w-md flex justify-center flex-col">
<div class="min-h-screen container mx-auto px-4 sm:px-0 sm:max-w-md flex justify-center flex-col">
<h2 class="text-2xl font-bold text-center mb-8">Login to your account</h2>
<form hx-post="/signin" hx-target="#login-result">
@@ -42,4 +42,4 @@
<a href="/signup" hx-boost="true" class="link link-primary">Sign up</a>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@@ -7,7 +7,7 @@
}
</style>
<div class="min-h-screen container mx-auto max-w-md flex justify-center flex-col">
<div class="min-h-screen container mx-auto px-4 sm:px-0 sm:max-w-md flex justify-center flex-col">
<h2 class="text-2xl font-bold text-center mb-8">Create your account</h2>
<form hx-post="/signup" hx-target="#signup-result" class="">
@@ -41,4 +41,4 @@
<a href="/signin" hx-boost="true" class="link link-primary">Sign in</a>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@@ -6,16 +6,16 @@
<!-- Navbar -->
<nav class="navbar bg-base-200">
<div class="flex-1">
<a class="btn text-xl border-transparent btn-outline btn-primary" href="/">Minne</a>
<a class="btn text-2xl border-transparent btn-outline btn-primary" href="/">Minne</a>
</div>
<div>
<ul class="menu menu-horizontal px-1">
{% if user %}
<li><a hx-boost="true" href="/account">Account</a></li>
<li><a hx-boost="true" class="" href="/account">Account</a></li>
<li><a hx-boost="true" href="/signout">Sign out</a></li>
{% else %}
<li><a hx-boost="true" href="/signin">Login</a></li>
<li><a hx-boost="true" href="/signup">Sign up</a></li>
<li><a hx-boost="true" class="" href="/signin">Login</a></li>
<li><a hx-boost="true" class="" href="/signup">Sign up</a></li>
{% endif %}
</ul>
</div>

View File

@@ -1,27 +0,0 @@
{% extends "head_base.html" %}
{% block body %}
<body class="min-h-screen">
<nav class="navbar bg-base-200">
<div class="flex-1">
<a class="btn text-xl border-transparent btn-outline btn-primary" href="/">Minne</a>
</div>
<div class="flex-none">
<ul class="menu menu-horizontal px-1">
{% if user %}
<li><a hx-boost="true" href="/account">Account</a></li>
<li><a hx-boost="true" href="/signout">Sign out</a></li>
{% else %}
<li><a hx-boost="true" href="/signin">Login</a></li>
<li><a hx-boost="true" href="/signup">Sign up</a></li>
{% endif %}
</ul>
</div>
</nav>
<main class="container mx-auto ">
{% block content %}{% endblock %}
</main>
</body>
{% endblock %}

View File

@@ -1,34 +0,0 @@
{% extends "body_base.html" %}
{% block main %}
{% if user %}
<p class="text-blue-950">HI</p>
{% else %}
<div class="flex flex-col items-center justify-center min-h-[80vh] space-y-8">
<!-- Hero Section -->
<div class="text-center space-y-4 mb-8">
<h1
class="text-5xl font-bold bg-gradient-to-r from-blue-400 via-purple-500 to-pink-500 text-transparent bg-clip-text">
Welcome to minne
</h1>
<p class="text-gray-400 text-xl">
An experiment in creating a second brain
</p>
<p class="text-gray-400 text-lg">
There are {{queue_length}} messages queued for ingression.
</p>
</div>
<!-- Search Bar -->
<div class="w-full max-w-2xl">
<input type="text" placeholder="Enter your search query" class="input input-bordered w-full" name="query"
hx-get="/search" hx-target="#search-results" />
</div>
<!-- Search Results -->
<div id="search-results" class="w-full max-w-2xl mt-4">
<!-- Results will be populated here by HTMX -->
</div>
</div>
{% endif %}
{% endblock %}

51
templates/index/hero.html Normal file
View File

@@ -0,0 +1,51 @@
<div class="hero">
<div class="hero-content text-center">
<div class="max-w-4xl space-y-8">
<!-- Hero Section -->
<h1
class="text-5xl sm:text-6xl py-4 pt-10 font-bold bg-gradient-to-r from-primary to-secondary text-transparent bg-clip-text">
Simplify Your Knowledge Management
</h1>
<p class="text-xl text-base-content/70">
Capture, connect, and retrieve your knowledge effortlessly with Minne
</p>
<!-- Features Grid -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 my-12">
<div class="card bg-base-100 shadow-hover">
<div class="card-body items-center">
<div class="skeleton h-32 w-32 rounded-full"></div>
<h3 class="card-title">Easy Capture</h3>
<p>Save anything instantly - texts, links, images, and more</p>
</div>
</div>
<div class="card bg-base-100 shadow-hover">
<div class="card-body items-center">
<div class="skeleton h-32 w-32 rounded-full"></div>
<h3 class="card-title">Smart Analysis</h3>
<p>AI-powered content analysis and organization</p>
</div>
</div>
<div class="card bg-base-100 shadow-hover">
<div class="card-body items-center">
<div class="skeleton h-32 w-32 rounded-full"></div>
<h3 class="card-title">Knowledge Graph</h3>
<p>Visualize connections between your ideas</p>
</div>
</div>
</div>
<!-- CTA -->
<div class="space-y-4">
<div class="flex justify-center gap-4">
<button class="btn btn-primary btn-lg">Get Started</button>
<button class="btn btn-outline btn-lg">Learn More</button>
</div>
<p class="text-sm text-base-content/60">
Currently processing {{queue_length}} items in queue
</p>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,8 @@
{% extends "body_base.html" %}
{% block main %}
{% if user %}
{% include 'index/signed_in_view.html' %}
{% else %}
{% include 'index/hero.html' %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,29 @@
<div class="container mx-auto p-4 max-w-screen-lg flex-col flex justify-center gap-6">
<!-- Search Bar -->
<div class="form-control w-full mx-auto mt-8">
<h1 class="textl-lg text-center pb-5">So here you can search all your ingressed documents</h1>
<input type="text" placeholder="Search your knowledge base" class="input input-bordered w-full" name="query"
hx-get="/search" hx-target="#search-results" />
<div id="search-results" class="mt-4">
<!-- Results will be populated here by HTMX -->
</div>
</div>
<!-- Recent Activity -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Recent Activity</h2>
<div class="skeleton h-32 w-full"></div>
</div>
</div>
<!-- Quick Actions - Modified button to link to ingress form -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Quick Actions</h2>
<div class="flex gap-4">
<a class="btn btn-primary" href="/ingress" hx-boost="true">Add Content</a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,20 @@
{% extends "body_base.html" %}
{% block main %}
<div class="container px-4 max-w-screen-lg">
<form class="space-y-2" hx-post="/ingress" enctype="multipart/form-data">
<h1 class="text-2xl">Add content to the database </h1>
<label class="label label-text">Instructions</label>
<textarea name="instructions" class="textarea w-full input-bordered"
placeholder="Enter instructions for the AI here, help it understand what its seeing or how it should relate to the database"></textarea>
<label class="label label-text">Content (optional)</label>
<textarea name="content" class="textarea w-full input-bordered" placeholder="Additional content"></textarea>
<label class="label label-text">Category</label>
<input type="text" name="category" class="input input-bordered" placeholder="Category for ingress">
<label class="label label-text">Files</label>
<input type="file" name="files" multiple class="file-input file-input-bordered" />
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="ingress-result"></div>
</div>
{% endblock %}

View File

@@ -3,5 +3,6 @@
\[x\] templating
\[x\] redirects
\[\] hx-redirect
\[\] macro for pagedata?
\[x\] macro for pagedata?
\[\] add more config structs for clarity
\[\] user id to fileinfo and data path?