From: Olaf Wintermann Date: Sat, 16 May 2026 11:30:46 +0000 (+0200) Subject: load notebook structure at startup X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=d0da5197c5fc72bb79251fccd44f9a3201e12df2;p=note.git load notebook structure at startup --- diff --git a/application/src/backend.rs b/application/src/backend.rs index a1fc41c..2826184 100644 --- a/application/src/backend.rs +++ b/application/src/backend.rs @@ -1,6 +1,6 @@ use std::future::Future; use std::pin::Pin; -use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, DbErr, EntityTrait, QueryFilter, ColumnTrait, Set}; +use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, DbErr, EntityTrait, QueryFilter, ColumnTrait, Set, QueryOrder}; use tokio::runtime::Runtime; use std::sync::{Arc}; use tokio::sync::mpsc; @@ -8,8 +8,9 @@ use tokio::sync::mpsc::UnboundedSender; use migration::{Migrator, MigratorTrait}; use ui_rs::ui; -use entity::profile; +use entity::{collection, profile}; use entity::profile::Entity as Profile; +use entity::collection::Entity as Collection; pub struct Backend { rt: Arc, @@ -115,6 +116,15 @@ impl Backend { Ok(profile) } + pub fn load_collections(&self, profile_id: i32) -> Result, DbErr> { + self.rt.block_on(async { + Collection::find() + .filter(collection::Column::ProfileId.eq(profile_id)) + .order_by_asc(collection::Column::Parent) + .all(&self.db).await + }) + } + pub fn start(self) -> BackendHandle { let backend = Arc::new(self); diff --git a/application/src/main.rs b/application/src/main.rs index 1f2f184..78ae303 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -30,9 +30,10 @@ mod window; mod backend; use std::env; +use entity::collection::{create_notebook_hierarchy, Node}; use ui_rs::{ui}; use ui_rs::ui::*; -use crate::backend::{Backend, BackendHandle, DynCmd}; +use crate::backend::{Backend, BackendHandle}; use crate::window::*; fn main() { @@ -45,10 +46,23 @@ fn main() { return; } }; + let profile_id = backend.current_profile.as_ref().unwrap().id; + + let notebooks = match backend.load_collections(profile_id) { + Ok(notebooks) => create_notebook_hierarchy(notebooks), + Err(e) => { + let msg = format!("Error loading collections: {:?}", e); + ui::app_run_startup_error("Error", msg.as_str()); + return; + } + }; let handle = backend.start(); - let mut app = App { backend: handle }; + let mut app = App { + backend: handle, + notebooks: notebooks, + }; ui::app_run::(&mut app); } @@ -100,6 +114,8 @@ fn init_backend() -> Result { struct App { backend: BackendHandle, + + notebooks: Vec, } @@ -111,7 +127,8 @@ impl Application for App { create_toolbar(app); - create_window(app); + let window = create_window(app); + window.window_data(|data| init_window_data(data, self)); } } diff --git a/application/src/window.rs b/application/src/window.rs index a83100d..2880d3a 100644 --- a/application/src/window.rs +++ b/application/src/window.rs @@ -28,11 +28,13 @@ use ui_rs::{action, ui_actions, UiModel}; use ui_rs::ui::*; +use crate::App; +use entity::collection::Model as Collection; #[derive(UiModel, Default)] pub struct MainWindow { #[bind] - notebooks: UiSourceList + notebooks: UiSourceList } #[ui_actions] @@ -43,7 +45,7 @@ impl MainWindow { } } -pub fn create_window(app: &AppContext) { +pub fn create_window(app: &AppContext) -> UiObject { let windowdata: MainWindow = Default::default(); let window = app.splitview_window("note", true, windowdata, |obj, data| { @@ -51,6 +53,9 @@ pub fn create_window(app: &AppContext) { obj.sourcelist(|b|{ b.fill(true); b.value(&data.notebooks); + b.getvalue(|elm,_row,item|{ + item.label = Some(elm.name.clone()); + }); }); }); @@ -81,8 +86,24 @@ pub fn create_window(app: &AppContext) { }); }); }); - }) + }); }); window.show(); -} \ No newline at end of file + window +} + +pub fn init_window_data(window: &mut MainWindow, data: &App) { + for elm in data.notebooks.iter() { + let mut notebook = SubList::new(); + notebook.set_header(elm.collection.name.as_str()); + + let sublist_data = notebook.list().data(); + for child in elm.children.iter() { + sublist_data.push(child.collection.clone()); + } + + window.notebooks.push(notebook); + } + window.notebooks.update(); +} diff --git a/entity/src/collection.rs b/entity/src/collection.rs index ecc0c1a..656d145 100644 --- a/entity/src/collection.rs +++ b/entity/src/collection.rs @@ -1,4 +1,6 @@ +use std::collections::HashMap; use sea_orm::entity::prelude::*; +use crate::collection; #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] #[sea_orm(table_name = "collection")] @@ -8,10 +10,15 @@ pub struct Model { pub profile_id: i32, pub name: String, - pub path: String, + pub parent: String, pub icon: String, pub kind: CollectionType, +} +impl Model { + pub fn depth(&self) -> usize { + self.parent.chars().filter(|c| *c == '/').count() + } } #[derive(EnumIter, DeriveActiveEnum, Clone, Debug, PartialEq)] @@ -27,3 +34,55 @@ pub enum CollectionType { pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} + + +#[derive(Clone)] +pub struct Node { + pub collection: Model, + pub children: Vec +} + +struct Path { + str: String, + depth: usize, +} + +pub fn create_notebook_hierarchy(list: Vec) -> Vec { + let mut tree = HashMap::new(); + let mut order = Vec::new(); + + // create a map of all nodes with the full path as key + for elm in list { + let path_str = format!("{}/{}", elm.parent, elm.name); + let depth = elm.depth(); + let path = Path { str: path_str, depth: depth }; + + let node = Node { + collection: elm, + children: Vec::new() + }; + + tree.insert(path.str.clone(), node); + order.push(path); + } + + // sort nodes by depth, because we need to process the tree from bottom to top + order.sort_by(|a, b| { + b.depth.cmp(&a.depth) + }); + + // transform node map into a tree + let mut nodes = Vec::new(); + + for path in order { + if let Some(node) = tree.remove(&path.str) { + if let Some(parent) = tree.get_mut(&node.collection.parent) { + parent.children.push(node); + } else { + nodes.push(node); + } + } + } + + nodes +} diff --git a/migration/src/m20260502_184134_create_settings.rs b/migration/src/m20260502_184134_create_settings.rs index 5f66a18..33e01c4 100644 --- a/migration/src/m20260502_184134_create_settings.rs +++ b/migration/src/m20260502_184134_create_settings.rs @@ -27,7 +27,7 @@ impl MigrationTrait for Migration { .col(pk_auto("collection_id")) .col(integer("profile_id")) .col(string("name")) - .col(string("path")) + .col(string("parent")) .col(string("icon")) .col(integer("kind")) .foreign_key(