mirror of
https://github.com/perstarkse/minne.git
synced 2026-04-26 10:48:37 +02:00
wip: plotly & additional documentation
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
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(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
@@ -1 +1,79 @@
|
||||
pub mod index;
|
||||
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!(DocumentationData, "do_not_use_this", {
|
||||
user: Option<User>,
|
||||
current_path: String
|
||||
});
|
||||
|
||||
pub async fn show_privacy_policy(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let output = render_template(
|
||||
"documentation/privacy.html",
|
||||
DocumentationData {
|
||||
user: auth.current_user,
|
||||
current_path: "/privacy_policy".to_string(),
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
pub async fn show_get_started(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let output = render_template(
|
||||
"documentation/get_started.html",
|
||||
DocumentationData {
|
||||
user: auth.current_user,
|
||||
current_path: "/get-started".to_string(),
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
pub async fn show_mobile_friendly(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let output = render_template(
|
||||
"documentation/mobile_friendly.html",
|
||||
DocumentationData {
|
||||
user: auth.current_user,
|
||||
current_path: "/mobile-friendly".to_string(),
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
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(
|
||||
"documentation/index.html",
|
||||
DocumentationData {
|
||||
user: auth.current_user,
|
||||
current_path: "/index".to_string(),
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::{IntoResponse, Redirect},
|
||||
};
|
||||
use axum_session::Session;
|
||||
use axum_session_auth::AuthSession;
|
||||
use axum_session_surreal::SessionSurrealPool;
|
||||
use surrealdb::{engine::any::Any, Surreal};
|
||||
use tokio::join;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
error::{AppError, HtmlError},
|
||||
page_data,
|
||||
server::{
|
||||
routes::html::{render_block, render_template},
|
||||
AppState,
|
||||
},
|
||||
storage::{
|
||||
db::{delete_item, get_item},
|
||||
types::{
|
||||
file_info::FileInfo, job::Job, knowledge_entity::KnowledgeEntity,
|
||||
knowledge_relationship::KnowledgeRelationship, text_chunk::TextChunk,
|
||||
text_content::TextContent, user::User,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
page_data!(KnowledgeBaseData, "knowledge/base.html", {
|
||||
entities: Vec<KnowledgeEntity>,
|
||||
relationships: Vec<KnowledgeRelationship>,
|
||||
user: User
|
||||
});
|
||||
|
||||
pub async fn show_knowledge_page(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
// Early return if the user is not authenticated
|
||||
let user = match auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/signin").into_response()),
|
||||
};
|
||||
|
||||
let entities = User::get_knowledge_entities(&user.id, &state.surreal_db_client)
|
||||
.await
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
info!("Got entities ok");
|
||||
|
||||
let relationships = User::get_knowledge_relationships(&user.id, &state.surreal_db_client)
|
||||
.await
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
let output = render_template(
|
||||
KnowledgeBaseData::template_name(),
|
||||
KnowledgeBaseData {
|
||||
entities,
|
||||
relationships,
|
||||
user,
|
||||
},
|
||||
state.templates,
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
@@ -1 +1,112 @@
|
||||
pub mod entities;
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::{IntoResponse, Redirect},
|
||||
};
|
||||
use axum_session::Session;
|
||||
use axum_session_auth::AuthSession;
|
||||
use axum_session_surreal::SessionSurrealPool;
|
||||
use plotly::{Configuration, Layout, Plot, Scatter};
|
||||
use surrealdb::{engine::any::Any, Surreal};
|
||||
use tokio::join;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
error::{AppError, HtmlError},
|
||||
page_data,
|
||||
server::{
|
||||
routes::html::{render_block, render_template},
|
||||
AppState,
|
||||
},
|
||||
storage::{
|
||||
db::{delete_item, get_item},
|
||||
types::{
|
||||
file_info::FileInfo, job::Job, knowledge_entity::KnowledgeEntity,
|
||||
knowledge_relationship::KnowledgeRelationship, text_chunk::TextChunk,
|
||||
text_content::TextContent, user::User,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
page_data!(KnowledgeBaseData, "knowledge/base.html", {
|
||||
entities: Vec<KnowledgeEntity>,
|
||||
relationships: Vec<KnowledgeRelationship>,
|
||||
user: User,
|
||||
plot_html: String
|
||||
});
|
||||
|
||||
pub async fn show_knowledge_page(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
// Early return if the user is not authenticated
|
||||
let user = match auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/signin").into_response()),
|
||||
};
|
||||
|
||||
let entities = User::get_knowledge_entities(&user.id, &state.surreal_db_client)
|
||||
.await
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
info!("Got entities ok");
|
||||
|
||||
let relationships = User::get_knowledge_relationships(&user.id, &state.surreal_db_client)
|
||||
.await
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
// In your handler function
|
||||
let mut plot = Plot::new();
|
||||
|
||||
// Create node positions (you might want to use a proper layout algorithm)
|
||||
let node_x: Vec<f64> = entities.iter().enumerate().map(|(i, _)| i as f64).collect();
|
||||
let node_y: Vec<f64> = vec![0.0; entities.len()];
|
||||
let node_text: Vec<String> = entities.iter().map(|e| e.description.clone()).collect();
|
||||
|
||||
// Add nodes
|
||||
let nodes = Scatter::new(node_x.clone(), node_y.clone())
|
||||
.mode(plotly::common::Mode::Markers)
|
||||
.text_array(node_text)
|
||||
.name("Entities")
|
||||
.hover_template("%{text}");
|
||||
|
||||
// Add edges
|
||||
let mut edge_x = Vec::new();
|
||||
let mut edge_y = Vec::new();
|
||||
for rel in &relationships {
|
||||
let from_idx = entities.iter().position(|e| e.id == rel.out).unwrap_or(0);
|
||||
let to_idx = entities.iter().position(|e| e.id == rel.in_).unwrap_or(0);
|
||||
|
||||
edge_x.extend_from_slice(&[from_idx as f64, to_idx as f64, std::f64::NAN]);
|
||||
edge_y.extend_from_slice(&[0.0, 0.0, std::f64::NAN]);
|
||||
}
|
||||
|
||||
let edges = Scatter::new(edge_x, edge_y)
|
||||
.mode(plotly::common::Mode::Lines)
|
||||
.name("Relationships");
|
||||
|
||||
plot.add_trace(edges);
|
||||
plot.add_trace(nodes);
|
||||
|
||||
let layout = Layout::new()
|
||||
.title("Knowledge Graph")
|
||||
.show_legend(false)
|
||||
.height(600);
|
||||
|
||||
plot.set_layout(layout);
|
||||
|
||||
// Convert to HTML
|
||||
let html = plot.to_html();
|
||||
|
||||
let output = render_template(
|
||||
KnowledgeBaseData::template_name(),
|
||||
KnowledgeBaseData {
|
||||
entities,
|
||||
relationships,
|
||||
user,
|
||||
plot_html: html,
|
||||
},
|
||||
state.templates,
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ pub mod gdpr;
|
||||
pub mod index;
|
||||
pub mod ingress_form;
|
||||
pub mod knowledge;
|
||||
pub mod privacy_policy;
|
||||
pub mod search_result;
|
||||
pub mod signin;
|
||||
pub mod signout;
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
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!(PrivacyPolicyData, "documentation/privacy.html", {
|
||||
user: Option<User>
|
||||
});
|
||||
|
||||
pub async fn show_privacy_policy(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
let output = render_template(
|
||||
PrivacyPolicyData::template_name(),
|
||||
PrivacyPolicyData {
|
||||
user: auth.current_user,
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
Reference in New Issue
Block a user