Compare commits

..

No commits in common. "83d5858a458f7273cd1f9a835e36f8c5001cc546" and "9337b98ad3c4b10a89ed2db9cc336e36230ae75c" have entirely different histories.

8 changed files with 57 additions and 113 deletions

View File

@ -1,2 +0,0 @@
[ ] Add RelationshipKind to Notes passed out
[ ] Add KastenKind to Backreferences passed out

View File

@ -6,8 +6,7 @@ mod structs;
pub use crate::errors::NoteStoreError; pub use crate::errors::NoteStoreError;
pub use crate::store::NoteStore; pub use crate::store::NoteStore;
pub use crate::structs::{Note, NoteKind, NoteRelationship, KastenRelationship}; pub use crate::structs::{Note, NoteKind};
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -82,22 +81,22 @@ mod tests {
// <- 2 <- 4 // <- 2 <- 4
let note1 = make_new_note("1"); let note1 = make_new_note("1");
let note1_id = storagepool.add_note(&note1, &root.id, Some(0)).await; let note1_id = storagepool.add_note(&note1, &root.id, 0).await;
assert!(note1_id.is_ok(), "{:?}", note1_id); assert!(note1_id.is_ok(), "{:?}", note1_id);
let note1_id = note1_id.unwrap(); let note1_id = note1_id.unwrap();
let note2 = make_new_note("2"); let note2 = make_new_note("2");
let note2_id = storagepool.add_note(&note2, &root.id, Some(0)).await; let note2_id = storagepool.add_note(&note2, &root.id, 0).await;
assert!(note2_id.is_ok(), "{:?}", note2_id); assert!(note2_id.is_ok(), "{:?}", note2_id);
let note2_id = note2_id.unwrap(); let note2_id = note2_id.unwrap();
let note3 = make_new_note("3"); let note3 = make_new_note("3");
let note3_id = storagepool.add_note(&note3, &note1_id, Some(0)).await; let note3_id = storagepool.add_note(&note3, &note1_id, 0).await;
assert!(note3_id.is_ok(), "{:?}", note3_id); assert!(note3_id.is_ok(), "{:?}", note3_id);
let _note3_id = note3_id.unwrap(); let _note3_id = note3_id.unwrap();
let note4 = make_new_note("4"); let note4 = make_new_note("4");
let note4_id = storagepool.add_note(&note4, &note2_id, Some(0)).await; let note4_id = storagepool.add_note(&note4, &note2_id, 0).await;
assert!(note4_id.is_ok(), "{:?}", note4_id); assert!(note4_id.is_ok(), "{:?}", note4_id);
let _note4_id = note4_id.unwrap(); let _note4_id = note4_id.unwrap();

View File

@ -16,7 +16,7 @@ CREATE TABLE notes (
CREATE INDEX note_ids ON notes (id); CREATE INDEX note_ids ON notes (id);
CREATE TABLE favorites ( CREATE TABLE favorites (
id TEXT NOT NULL UNIQUE, id TEXT NOT NULL,
location INTEGER NOT NULL, location INTEGER NOT NULL,
FOREIGN KEY (id) REFERENCES notes (id) ON DELETE CASCADE FOREIGN KEY (id) REFERENCES notes (id) ON DELETE CASCADE
); );
@ -32,9 +32,7 @@ CREATE TABLE note_relationships (
kind TEXT NOT NULL, kind TEXT NOT NULL,
-- If either note disappears, we want all the edges to disappear as well. -- If either note disappears, we want all the edges to disappear as well.
FOREIGN KEY (note_id) REFERENCES notes (id) ON DELETE CASCADE, FOREIGN KEY (note_id) REFERENCES notes (id) ON DELETE CASCADE,
FOREIGN KEY (parent_id) REFERENCES notes (id) ON DELETE CASCADE, FOREIGN KEY (parent_id) REFERENCES notes (id) ON DELETE CASCADE
UNIQUE (note_id, parent_id),
CHECK (note_id <> parent_id)
); );
-- This table represents the graph of data relating notes to kastens. -- This table represents the graph of data relating notes to kastens.
@ -45,8 +43,6 @@ CREATE TABLE note_kasten_relationships (
kind TEXT NOT NULL, kind TEXT NOT NULL,
-- If either note disappears, we want all the edges to disappear as well. -- If either note disappears, we want all the edges to disappear as well.
FOREIGN KEY (note_id) REFERENCES notes (id) ON DELETE CASCADE, FOREIGN KEY (note_id) REFERENCES notes (id) ON DELETE CASCADE,
FOREIGN KEY (kasten_id) REFERENCES notes (id) ON DELETE CASCADE, FOREIGN KEY (kasten_id) REFERENCES notes (id) ON DELETE CASCADE
UNIQUE (note_id, kasten_id),
CHECK (note_id <> kasten_id)
); );

View File

@ -137,7 +137,7 @@ impl NoteStore {
Ok((vec![Note::from(zettlekasten)], vec![])) Ok((vec![Note::from(zettlekasten)], vec![]))
} }
pub async fn add_note(&self, note: &NewNote, parent_id: &str, location: Option<i64>) -> NoteResult<String> { pub async fn add_note(&self, note: &NewNote, parent_id: &str, location: i64) -> NoteResult<String> {
self.insert_note( self.insert_note(
note, note,
&ParentId(parent_id.to_string()), &ParentId(parent_id.to_string()),
@ -229,18 +229,16 @@ impl NoteStore {
&self, &self,
note: &NewNote, note: &NewNote,
parent_id: &ParentId, parent_id: &ParentId,
location: Option<i64>, location: i64,
kind: RelationshipKind, kind: RelationshipKind,
) -> NoteResult<String> { ) -> NoteResult<String> {
if let Some(location) = location { if location < 0 {
if location < 0 { return Err(NoteStoreError::InvalidNoteStructure(
return Err(NoteStoreError::InvalidNoteStructure( "Add note: A negative position is not valid.".to_string(),
"Add note: A negative location is not valid.".to_string(), ));
)); }
}
}
if parent_id.is_empty() { if parent_id.is_empty() {
return Err(NoteStoreError::InvalidNoteStructure( return Err(NoteStoreError::InvalidNoteStructure(
"Add note: A parent note ID is required.".to_string(), "Add note: A parent note ID is required.".to_string(),
)); ));
@ -261,14 +259,10 @@ impl NoteStore {
let references = build_references(&note.content); let references = build_references(&note.content);
let mut tx = self.0.begin().await?; let mut tx = self.0.begin().await?;
let location = { let location = cmp::min(
let max_child = assert_max_child_location_for_note(&mut tx, parent_id).await? + 1; assert_max_child_location_for_note(&mut tx, parent_id).await? + 1,
if let Some(location) = location { location,
cmp::min(max_child, location) );
} else {
max_child
}
};
let note_id = NoteId(note.id.clone()); let note_id = NoteId(note.id.clone());
insert_note(&mut tx, &note).await?; insert_note(&mut tx, &note).await?;

View File

@ -198,7 +198,7 @@ pub(crate) struct NoteRelationshipRow {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct NoteRelationship { pub(crate) struct NoteRelationship {
pub parent_id: String, pub parent_id: String,
pub note_id: String, pub note_id: String,
pub location: i64, pub location: i64,
@ -224,7 +224,7 @@ pub(crate) struct KastenRelationshipRow {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct KastenRelationship { pub(crate) struct KastenRelationship {
pub note_id: String, pub note_id: String,
pub kasten_id: String, pub kasten_id: String,
pub kind: KastenRelationshipKind, pub kind: KastenRelationshipKind,

View File

@ -13,41 +13,28 @@ mod make_tree;
mod structs; mod structs;
use nm_store::{NoteStore, NoteStoreError, NewNote}; use nm_store::{NoteStore, NoteStoreError, NewNote};
use crate::structs::{Page, Note}; use crate::structs::Page;
use crate::make_tree::{make_note_tree, make_backreferences}; use crate::make_tree::make_tree;
#[derive(Debug)] #[derive(Debug)]
pub struct Notesmachine(pub(crate) NoteStore); pub struct Notesmachine(pub(crate) NoteStore);
type Result<T> = core::result::Result<T, NoteStoreError>; type Result<T> = core::result::Result<T, NoteStoreError>;
pub fn make_page(foundtree: &Note, backreferences: Vec<Vec<Note>>) -> Page {
Page {
slug: foundtree.id,
title: foundtree.content,
creation_date: foundtree.creation_date,
updated_date: foundtree.updated_date,
lastview_date: foundtree.lastview_date,
deleted_date: foundtree.deleted_date,
notes: foundtree.children,
backreferences: backreferences
}
}
impl Notesmachine { impl Notesmachine {
pub async fn new(url: &str) -> Result<Self> { pub async fn new(url: &str) -> Result<Self> {
let notestore = NoteStore::new(url).await?; let notestore = NoteStore::new(url).await?;
Ok(Notesmachine(notestore)) Ok(Notesmachine(notestore))
} }
pub async fn get_page_via_slug(&self, slug: &str) -> Result<Page> { pub async fn get_box_via_slug(&self, slug: &str) -> Result<Page> {
let (rawtree, rawbackreferences) = self.0.get_kasten_by_slug(slug).await?; let (rawpage, rawnotes) = self.0.get_page_by_slug(slug).await?;
Ok(make_page(&make_note_tree(&rawtree), make_backreferences(&rawbackreferences))) Ok(make_tree(&rawpage, &rawnotes))
} }
pub async fn get_page(&self, title: &str) -> Result<Page> { pub async fn get_box(&self, title: &str) -> Result<Page> {
let (rawtree, rawbackreferences) = self.0.get_kasten_by_title(title).await?; let (rawpage, rawnotes) = self.0.get_page_by_title(title).await?;
Ok(make_page(&make_note_tree(&rawtree), make_backreferences(&rawbackreferences))) Ok(make_tree(&rawpage, &rawnotes))
} }
// TODO: // TODO:

View File

@ -1,12 +1,8 @@
use crate::structs::{Note, Page}; use crate::structs::{Note, Page};
use nm_store::NoteKind; use nm_store::{RawNote, RawPage};
fn make_note_tree_from(rawnotes: &[nm_store::Note], root_id: &str) -> Note { fn make_note_tree(rawnotes: &[RawNote], root: i64) -> Note {
let the_note = { let the_note = rawnotes.iter().find(|note| note.id == root).unwrap().clone();
let foundroots: Vec<&nm_store::Note> = rawnotes.iter().filter(|note| note.id == root_id).collect();
debug_assert!(foundroots.len() == 1);
foundroots.iter().next().unwrap().clone()
};
// The special case of the root node must be filtered out here to // The special case of the root node must be filtered out here to
// prevent the first pass from smashing the stack in an infinite // prevent the first pass from smashing the stack in an infinite
@ -15,61 +11,35 @@ fn make_note_tree_from(rawnotes: &[nm_store::Note], root_id: &str) -> Note {
// are faster. // are faster.
let mut children = rawnotes let mut children = rawnotes
.iter() .iter()
.filter(|note| note.parent_id.is_some() && note.parent_id.unwrap() == root_id && note.id != the_note.id) .filter(|note| note.parent_id == root && note.id != root)
.map(|note| make_note_tree_from(rawnotes, &note.id)) .map(|note| make_note_tree(rawnotes, note.id))
.collect::<Vec<Note>>(); .collect::<Vec<Note>>();
children.sort_unstable_by(|a, b| a.location.cmp(&b.location)); children.sort_unstable_by(|a, b| a.position.cmp(&b.position));
Note { Note {
id: the_note.id, uuid: the_note.uuid,
parent_id: the_note.parent_id, parent_uuid: the_note.parent_uuid,
content: the_note.content, content: the_note.content,
kind: the_note.kind.to_string(), notetype: the_note.notetype,
location: the_note.location, position: the_note.position,
creation_date: the_note.creation_date, creation_date: the_note.creation_date,
updated_date: the_note.updated_date, updated_date: the_note.updated_date,
lastview_date: the_note.updated_date, lastview_date: the_note.updated_date,
deleted_date: the_note.deleted_date, deleted_date: the_note.deleted_date,
children: children, children: vec![],
} }
} }
pub(crate) fn make_note_tree(rawnotes: &[nm_store::Note]) -> Note { pub(crate) fn make_tree(rawpage: &RawPage, rawnotes: &[RawNote]) -> Page {
let the_root = { let the_page = rawpage.clone();
let foundroots: Vec<&nm_store::Note> = rawnotes.iter().filter(|note| note.kind == NoteKind::Kasten).collect();
debug_assert!(foundroots.len() == 1);
foundroots.iter().next().unwrap().clone()
};
make_note_tree_from(&rawnotes, &the_root.id)
}
fn add_child(rawnotes: &[nm_store::Note], acc: &mut Vec<Note>, note_id: &str) -> Vec<Note> { Page {
let child = rawnotes slug: the_page.slug,
.iter() title: the_page.title,
.find(|note| note.parent_id.is_some() && note.parent_id.unwrap() == note_id); creation_date: the_page.creation_date,
if let Some(c) = child { updated_date: the_page.updated_date,
acc.push(Note { lastview_date: the_page.updated_date,
id: c.id, deleted_date: the_page.deleted_date,
parent_id: Some(note_id.to_string()), root_note: make_note_tree(rawnotes, rawpage.note_id),
content: c.content,
kind: c.kind.to_string(),
location: c.location,
creation_date: c.creation_date,
updated_date: c.updated_date,
lastview_date: c.updated_date,
deleted_date: c.deleted_date,
children: vec![],
});
add_child(rawnotes, acc, &c.id)
} else {
acc.to_vec()
} }
} }
pub(crate) fn make_backreferences(rawnotes: &[nm_store::Note]) -> Vec<Vec<Note>> {
rawnotes
.iter()
.filter(|note| note.parent_id.is_none() && note.kind == NoteKind::Kasten)
.map(|root| add_child(rawnotes, &mut Vec::<Note>::new(), &root.id))
.collect()
}

View File

@ -3,11 +3,11 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Serialize, Deserialize, Debug)] #[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Note { pub struct Note {
pub id: String, pub uuid: String,
pub parent_id: Option<String>, pub parent_uuid: String,
pub content: String, pub content: String,
pub location: i64, pub position: i64,
pub kind: String, pub notetype: String,
pub creation_date: DateTime<Utc>, pub creation_date: DateTime<Utc>,
pub updated_date: DateTime<Utc>, pub updated_date: DateTime<Utc>,
pub lastview_date: DateTime<Utc>, pub lastview_date: DateTime<Utc>,
@ -15,6 +15,7 @@ pub struct Note {
pub children: Vec<Note>, pub children: Vec<Note>,
} }
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Page { pub struct Page {
pub slug: String, pub slug: String,
pub title: String, pub title: String,
@ -22,6 +23,5 @@ pub struct Page {
pub updated_date: DateTime<Utc>, pub updated_date: DateTime<Utc>,
pub lastview_date: DateTime<Utc>, pub lastview_date: DateTime<Utc>,
pub deleted_date: Option<DateTime<Utc>>, pub deleted_date: Option<DateTime<Utc>>,
pub notes: Vec<Note>, pub root_note: Note,
pub backreferences: Vec<Vec<Note>>,
} }