147 lines
5.0 KiB
Rust
147 lines
5.0 KiB
Rust
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
//! # Tree Layer
|
|
//!
|
|
//! This layer provides an interface between the storage layer and
|
|
//! the outside world. It provides all of the basic logic, including
|
|
//! the premise that a note without a parent is automatically
|
|
//! made a child of the day's notepad.
|
|
|
|
mod make_tree;
|
|
mod structs;
|
|
|
|
use crate::make_tree::{make_backreferences, make_note_tree};
|
|
use crate::structs::{Note, Page};
|
|
use chrono::{DateTime, Utc};
|
|
use nm_store::{NewNote, NoteStore, NoteStoreError};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Notesmachine(pub(crate) NoteStore);
|
|
|
|
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 {
|
|
pub async fn new(url: &str) -> Result<Self> {
|
|
let notestore = NoteStore::new(url).await?;
|
|
Ok(Notesmachine(notestore))
|
|
}
|
|
|
|
pub async fn get_page_via_slug(&self, slug: &str) -> Result<Page> {
|
|
let (rawtree, rawbackreferences) = self.0.get_kasten_by_slug(slug).await?;
|
|
Ok(make_page(
|
|
&make_note_tree(&rawtree),
|
|
make_backreferences(&rawbackreferences),
|
|
))
|
|
}
|
|
|
|
pub async fn get_page(&self, title: &str) -> Result<Page> {
|
|
let (rawtree, rawbackreferences) = self.0.get_kasten_by_title(title).await?;
|
|
Ok(make_page(
|
|
&make_note_tree(&rawtree),
|
|
make_backreferences(&rawbackreferences),
|
|
))
|
|
}
|
|
|
|
// TODO:
|
|
// You should be able to:
|
|
// Add a note that has no parent (gets added to "today")
|
|
// Add a note that specifies only the page (gets added to page/root)
|
|
// Add a note that has no location (gets tacked onto the end of the above)
|
|
// Add a note that specifies the date of creation.
|
|
pub async fn add_note(&self, note: &NewNote) -> Result<String> {
|
|
let mut note = note.clone();
|
|
if note.parent_id.is_none() {
|
|
note.parent_id = self.get_today_page().await?;
|
|
}
|
|
Ok(self.0.add_note(¬e))
|
|
}
|
|
|
|
// pub async fn reference_note(&self, note_id: &str, new_parent_id: &str, new_location: i64) -> Result<()> {
|
|
// todo!();
|
|
// }
|
|
//
|
|
// pub async fn embed_note(&self, note_id: &str, new_parent_id: &str, new_location: i64) -> Result<()> {
|
|
// todo!();
|
|
// }
|
|
|
|
pub async fn move_note(
|
|
&self,
|
|
note_id: &str,
|
|
old_parent_id: &str,
|
|
new_parent_id: &str,
|
|
location: i64,
|
|
) -> Result<()> {
|
|
self.0.move_note(note_id, old_parent_id, new_parent_id, location).await
|
|
}
|
|
|
|
pub async fn update_note(&self, note_id: &str, content: &str) -> Result<()> {
|
|
self.0.update_note_content(note_id, content).await
|
|
}
|
|
|
|
pub async fn delete_note(&self, note_id: &str, parent_note_id: &str) -> Result<()> {
|
|
self.0.delete_note(note_id, parent_note_id).await
|
|
}
|
|
}
|
|
|
|
// Private stuff
|
|
|
|
impl Notesmachine {
|
|
async fn get_today_page(&self) -> Result<String> {
|
|
let title = chrono::Utc::now().format("%F").to_string();
|
|
let (rawtree, _) = self.0.get_kasten_by_title(title).await?;
|
|
Ok(rawtree.id)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use tokio;
|
|
|
|
async fn fresh_inmemory_database() -> Notesmachine {
|
|
let notesmachine = Notesmachine::new("sqlite://:memory:").await;
|
|
assert!(notesmachine.is_ok(), "{:?}", notesmachine);
|
|
let notesmachine = notesmachine.unwrap();
|
|
let reset = notesmachine.0.reset_database().await;
|
|
assert!(reset.is_ok(), "{:?}", reset);
|
|
notesmachine
|
|
}
|
|
|
|
#[tokio::test(threaded_scheduler)]
|
|
async fn fetching_unfound_page_by_slug_works() {
|
|
let notesmachine = fresh_inmemory_database().await;
|
|
let unfoundpage = notesmachine.get_page_via_slug("nonexistent-slug").await;
|
|
assert!(unfoundpage.is_err());
|
|
}
|
|
|
|
#[tokio::test(threaded_scheduler)]
|
|
async fn fetching_unfound_page_by_title_works() {
|
|
let title = "Nonexistent Page";
|
|
let notesmachine = fresh_inmemory_database().await;
|
|
let newpageresult = notesmachine.get_page(&title).await;
|
|
assert!(newpageresult.is_ok(), "{:?}", newpageresult);
|
|
|
|
let newpage = newpageresult.unwrap();
|
|
assert_eq!(newpage.title, title, "{:?}", newpage.title);
|
|
assert_eq!(newpage.slug, "nonexistent-page", "{:?}", newpage.slug);
|
|
assert_eq!(newpage.root_note.content, "", "{:?}", newpage.root_note.content);
|
|
assert_eq!(newpage.root_note.notetype, "root", "{:?}", newpage.root_note.notetype);
|
|
assert_eq!(newpage.root_note.children.len(), 0, "{:?}", newpage.root_note.children);
|
|
}
|
|
}
|