mirror of
https://github.com/perstarkse/minne.git
synced 2026-03-11 21:12:01 +01:00
hero page, ingress form
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -13,6 +13,7 @@
|
||||
packages = [
|
||||
pkgs.openssl
|
||||
pkgs.nodejs
|
||||
pkgs.vscode-langservers-extracted
|
||||
];
|
||||
|
||||
# https://devenv.sh/languages/
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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>
|
||||
});
|
||||
|
||||
71
src/server/routes/html/ingress.rs
Normal file
71
src/server/routes/html/ingress.rs
Normal 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())
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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
51
templates/index/hero.html
Normal 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>
|
||||
8
templates/index/index.html
Normal file
8
templates/index/index.html
Normal 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 %}
|
||||
29
templates/index/signed_in_view.html
Normal file
29
templates/index/signed_in_view.html
Normal 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>
|
||||
20
templates/ingress_form.html
Normal file
20
templates/ingress_form.html
Normal 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 %}
|
||||
Reference in New Issue
Block a user