mirror of
https://github.com/perstarkse/minne.git
synced 2026-03-22 01:19:46 +01:00
feat: doc pages, finished refactor of ingress
This commit is contained in:
File diff suppressed because one or more lines are too long
52
package-lock.json
generated
52
package-lock.json
generated
@@ -5,6 +5,7 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"cssnano": "^7.0.6",
|
||||
"daisyui": "^4.12.23",
|
||||
@@ -160,6 +161,36 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography": {
|
||||
"version": "0.5.15",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz",
|
||||
"integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.castarray": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"postcss-selector-parser": "6.0.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
@@ -2275,6 +2306,20 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.castarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
@@ -2282,6 +2327,13 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.uniq": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"dev": "npm-run-all --parallel watch:css watch:tailwind"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"cssnano": "^7.0.6",
|
||||
"daisyui": "^4.12.23",
|
||||
|
||||
@@ -24,6 +24,7 @@ use zettle_db::{
|
||||
},
|
||||
html::{
|
||||
account::{delete_account, set_api_key, show_account_page},
|
||||
documentation::index::show_documentation_index,
|
||||
gdpr::{accept_gdpr, deny_gdpr},
|
||||
index::index_handler,
|
||||
ingress::{process_ingress_form, show_ingress_form},
|
||||
@@ -164,6 +165,7 @@ fn html_routes(
|
||||
"/signup",
|
||||
get(show_signup_form).post(process_signup_and_show_verification),
|
||||
)
|
||||
.route("/documentation", get(show_documentation_index))
|
||||
.nest_service("/assets", ServeDir::new("assets/"))
|
||||
.layer(
|
||||
AuthSessionLayer::<User, String, SessionSurrealPool<Any>, Surreal<Any>>::new(Some(
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
use super::ingress_object::IngressObject;
|
||||
use crate::{
|
||||
error::AppError,
|
||||
storage::{
|
||||
db::{get_item, SurrealDbClient},
|
||||
types::file_info::FileInfo,
|
||||
},
|
||||
};
|
||||
use crate::{error::AppError, storage::types::file_info::FileInfo};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::info;
|
||||
use url::Url;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use crate::{
|
||||
error::{ApiError, AppError},
|
||||
ingress::types::{
|
||||
ingress_input::{create_ingress_objects, IngressInput},
|
||||
ingress_object,
|
||||
},
|
||||
ingress::types::ingress_input::{create_ingress_objects, IngressInput},
|
||||
server::AppState,
|
||||
storage::types::{file_info::FileInfo, user::User},
|
||||
};
|
||||
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension, Json};
|
||||
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension};
|
||||
use axum_typed_multipart::{FieldData, TryFromMultipart, TypedMultipart};
|
||||
use futures::{future::try_join_all, TryFutureExt};
|
||||
use tempfile::NamedTempFile;
|
||||
@@ -31,7 +28,7 @@ pub async fn ingress_data(
|
||||
info!("Received input: {:?}", input);
|
||||
|
||||
let file_infos = try_join_all(input.files.into_iter().map(|file| {
|
||||
FileInfo::new(file, &state.surreal_db_client, &user.id).map_err(|e| AppError::from(e))
|
||||
FileInfo::new(file, &state.surreal_db_client, &user.id).map_err(AppError::from)
|
||||
}))
|
||||
.await?;
|
||||
|
||||
|
||||
31
src/server/routes/html/documentation/index.rs
Normal file
31
src/server/routes/html/documentation/index.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use axum::{extract::State, response::IntoResponse};
|
||||
use axum_session_auth::AuthSession;
|
||||
use axum_session_surreal::SessionSurrealPool;
|
||||
use surrealdb::{engine::any::Any, Surreal};
|
||||
|
||||
use crate::{
|
||||
error::HtmlError,
|
||||
page_data,
|
||||
server::{routes::html::render_template, AppState},
|
||||
storage::types::user::User,
|
||||
};
|
||||
|
||||
page_data!(IndexData, "documentation/index.html", {
|
||||
user: Option<User>
|
||||
});
|
||||
|
||||
pub async fn show_documentation_index(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let output = render_template(
|
||||
IndexData::template_name(),
|
||||
IndexData {
|
||||
user: auth.current_user,
|
||||
},
|
||||
state.templates.clone(),
|
||||
)
|
||||
.map_err(|e| HtmlError::from_template_error(e, state.templates.clone()))?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
1
src/server/routes/html/documentation/mod.rs
Normal file
1
src/server/routes/html/documentation/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod index;
|
||||
@@ -76,7 +76,7 @@ pub async fn process_ingress_form(
|
||||
},
|
||||
user.id.as_str(),
|
||||
)
|
||||
.map_err(|e| HtmlError::new(AppError::from(e), state.templates.clone()))?;
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
let futures: Vec<_> = ingress_objects
|
||||
.into_iter()
|
||||
@@ -86,9 +86,7 @@ pub async fn process_ingress_form(
|
||||
try_join_all(futures)
|
||||
.await
|
||||
.map_err(AppError::from)
|
||||
.map_err(|e| HtmlError::new(AppError::from(e), state.templates.clone()))?;
|
||||
// Process the ingress (implement your logic here)
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
Ok(Html("SuccessBRO!").into_response())
|
||||
// Ok((HxRedirect::from(Uri::from_static("/")), StatusCode::OK).into_response())
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use axum::response::Html;
|
||||
use minijinja_autoreload::AutoReloader;
|
||||
|
||||
pub mod account;
|
||||
pub mod documentation;
|
||||
pub mod gdpr;
|
||||
pub mod index;
|
||||
pub mod ingress;
|
||||
|
||||
@@ -4,10 +4,20 @@ module.exports = {
|
||||
'./templates/**/*',
|
||||
'!./templates/email/**/*'
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
theme: {
|
||||
extend: {
|
||||
typography: {
|
||||
DEFAULT: {
|
||||
css: {
|
||||
maxWidth: '90ch', // Override max-width for all prose instances
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('daisyui')],
|
||||
plugins: [
|
||||
require("@tailwindcss/typography"),
|
||||
require('daisyui')],
|
||||
daisyui: {
|
||||
themes: ["light", "dark"],
|
||||
},
|
||||
|
||||
@@ -5,45 +5,47 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
<div class="max-w-lg w-full">
|
||||
<h2 class="text-2xl font-bold text-center mb-8">Account Settings</h2>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Email</span>
|
||||
</label>
|
||||
<input type="email" name="email" value="{{ user.email }}" class="input input-bordered w-full" disabled />
|
||||
<main class="flex-grow flex justify-center items-center">
|
||||
<div class="max-w-lg w-full">
|
||||
<h2 class="text-2xl font-bold text-center mb-8">Account Settings</h2>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Email</span>
|
||||
</label>
|
||||
<input type="email" name="email" value="{{ user.email }}" class="input input-bordered w-full" disabled />
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">API key</span>
|
||||
</label>
|
||||
{% block api_key_section %}
|
||||
{% if user.api_key %}
|
||||
<input type="text" name="api-key" value="{{ user.api_key }}" class="input input-bordered w-full" disabled />
|
||||
{% else %}
|
||||
<button hx-post="/set-api-key" class="btn btn-secondary w-full" hx-swap="outerHTML">
|
||||
Create API-Key
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<button hx-post="/verify-email" class="btn btn-secondary w-full">
|
||||
Verify Email
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<button hx-get="/change-password" class="btn btn-primary w-full">
|
||||
Change Password
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<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="btn btn-error w-full">
|
||||
Delete Account
|
||||
</button>
|
||||
</div>
|
||||
<div id="account-result" class="mt-4"></div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">API key</span>
|
||||
</label>
|
||||
{% block api_key_section %}
|
||||
{% if user.api_key %}
|
||||
<input type="text" name="api-key" value="{{ user.api_key }}" class="input input-bordered w-full" disabled />
|
||||
{% else %}
|
||||
<button hx-post="/set-api-key" class="btn btn-secondary w-full" hx-swap="outerHTML">
|
||||
Create API-Key
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<button hx-post="/verify-email" class="btn btn-secondary w-full">
|
||||
Verify Email
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<button hx-get="/change-password" class="btn btn-primary w-full">
|
||||
Change Password
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<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="btn btn-error w-full">
|
||||
Delete Account
|
||||
</button>
|
||||
</div>
|
||||
<div id="account-result" class="mt-4"></div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -5,26 +5,27 @@
|
||||
<div class="min-h-screen flex flex-col">
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar bg-base-200">
|
||||
<div class="flex-1">
|
||||
<a class="btn text-2xl border-transparent btn-outline btn-primary" href="/" hx-boost="true">Minne</a>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="menu menu-horizontal px-1">
|
||||
{% if user %}
|
||||
<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" class="" href="/signin">Login</a></li>
|
||||
<li><a hx-boost="true" class="" href="/signup">Sign up</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="container mx-auto">
|
||||
<div class="flex-1">
|
||||
<a class="btn text-2xl border-transparent btn-outline btn-primary" href="/" hx-boost="true">Minne</a>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="menu menu-horizontal px-1">
|
||||
<li><a hx-boost="true" class="" href="/documentation">Docs</a></li>
|
||||
{% if user %}
|
||||
<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" class="" href="/signin">Login</a></li>
|
||||
<li><a hx-boost="true" class="" href="/signup">Sign up</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="flex-grow flex items-center justify-center">
|
||||
{% block main %}{% endblock %}
|
||||
</main>
|
||||
{% block main %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
{% endblock %}
|
||||
35
templates/documentation/index.html
Normal file
35
templates/documentation/index.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{% extends "body_base.html" %}
|
||||
{% block main %}
|
||||
<div class="flex justify-center flex-grow mt-0 sm:mt-4">
|
||||
<div class="container">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-[auto,1fr] gap-4 p-4">
|
||||
<!-- Documentation Menu -->
|
||||
<aside class="bg-base-200 rounded-lg p-4">
|
||||
{% include "documentation/menu.html" %}
|
||||
</aside>
|
||||
<!-- Main Content -->
|
||||
<article class="prose flex mx-auto justify-center flex-col">
|
||||
<h1 class="">Personalised Knowledge Management (PKM)</h1>
|
||||
<p class="">
|
||||
Personalised Knowledge Management (PKM) is a system designed to help individuals organise, store, and retrieve
|
||||
information effectively. It empowers users to create a personalised workflow for managing knowledge, enabling
|
||||
better decision-making and productivity.
|
||||
</p>
|
||||
<p class="">
|
||||
This documentation will guide you through the core concepts, tools, and best practices for building and
|
||||
maintaining your own PKM system.
|
||||
</p>
|
||||
<div class="card p-6 rounded-lg shadow-md">
|
||||
<h2 class="">Getting Started</h2>
|
||||
<p class="">
|
||||
To begin, explore the sections in the navigation menu. Each section provides detailed insights into
|
||||
different
|
||||
aspects of PKM, from foundational principles to advanced techniques.
|
||||
</p>
|
||||
<a href="/documentation/submenu1" class="btn btn-primary" hx-boost="true">Learn More</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
22
templates/documentation/menu.html
Normal file
22
templates/documentation/menu.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<ul class="menu bg-base-200 rounded-box">
|
||||
<li><a hx-boost="true" href="/documentation">Start</a></li>
|
||||
<li>
|
||||
<details open>
|
||||
<summary>Core Concepts</summary>
|
||||
<ul>
|
||||
<li><a hx-boost="true" href="/documentation/submenu1">What is PKM?</a></li>
|
||||
<li><a hx-boost="true" href="/documentation/submenu2">Benefits of PKM</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
<li>
|
||||
<details>
|
||||
<summary>Tools & Techniques</summary>
|
||||
<ul>
|
||||
<li><a hx-boost="true" href="/documentation/tools">Tools for PKM</a></li>
|
||||
<li><a hx-boost="true" href="/documentation/techniques">Effective Techniques</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
<li><a hx-boost="true" href="/documentation/faq">FAQ</a></li>
|
||||
</ul>
|
||||
@@ -1,12 +1,13 @@
|
||||
<div id="gdpr-banner" class="fixed card mx-auto max-w-screen-sm bg-neutral text-neutral-content bottom-0">
|
||||
<div id="gdpr-banner" class="fixed card mx-auto max-w-screen-sm mb-2 bg-neutral text-neutral-content bottom-0">
|
||||
<div class="card-body items-center text-center">
|
||||
<p class="text-sm"> We use cookies to enhance your experience. By continuing to visit this site, you agree to
|
||||
our use cookies.
|
||||
<a href="/privacy-policy" class="link link-primary">Learn more</a>
|
||||
</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-ghost" hx-post="/gdpr/deny" hx-target="#gdpr-banner" hx-swap="outerHTML">Deny</button>
|
||||
<button class="btn btn-primary" hx-post="/gdpr/accept" hx-target="#gdpr-banner"
|
||||
<div class="card-actions justify-end mt-2">
|
||||
<button class="btn btn-ghost btn-sm" hx-post="/gdpr/deny" hx-target="#gdpr-banner"
|
||||
hx-swap="outerHTML">Deny</button>
|
||||
<button class="btn btn-primary btn-sm" hx-post="/gdpr/accept" hx-target="#gdpr-banner"
|
||||
hx-swap="outerHTML">Accept</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Minne{% endblock %}</title>
|
||||
|
||||
<!-- <meta http-equiv="refresh" content="4"> -->
|
||||
|
||||
<!-- Preload critical assets -->
|
||||
<link rel="preload" href="assets/htmx.min.js" as="script">
|
||||
<link rel="preload" href="assets/style.css" as="style">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="hero">
|
||||
<div class="hero flex-grow flex justify-center ">
|
||||
<div class="hero-content text-center">
|
||||
<div class="max-w-4xl space-y-8">
|
||||
<!-- Hero Section -->
|
||||
|
||||
Reference in New Issue
Block a user