My personal-knowledge-system, with deeply integrated task tracking and long term goal planning capabilities.
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: renaming group also renames tags

+90 -35
+18 -18
.config/config.ron
··· 2 2 directory: "/Users/suri/dev/projects/filaments/ZettelKasten", 3 3 global_key_binds: { 4 4 "down": MoveDown, 5 - "ctrl-z": Suspend, 6 5 "ctrl-c": Quit, 7 6 "up": MoveUp, 7 + "ctrl-z": Suspend, 8 8 }, 9 9 zk: ( 10 10 keybinds: { 11 + "enter": OpenZettel, 11 12 "tab": SwitchTo( 12 13 page: Todo(Explorer), 13 14 ), 14 15 "ctrl-n": NewZettel, 15 - "enter": OpenZettel, 16 16 }, 17 17 ), 18 18 todo: ( 19 19 explorer: ( 20 20 keybinds: { 21 + "j": MoveDown, 21 22 "1": SwitchTo( 22 23 page: Todo(Explorer), 23 24 ), 24 - "j": MoveDown, 25 + "t": NewTask, 26 + "2": SwitchTo( 27 + page: Todo(Inspector), 28 + ), 29 + "shift-g": NewGroup, 30 + "g": NewSubGroup, 25 31 "enter": SwitchTo( 26 32 page: Todo(Inspector), 27 33 ), 28 34 "tab": SwitchTo( 29 35 page: Zk, 30 36 ), 31 - "g": NewSubGroup, 32 - "2": SwitchTo( 33 - page: Todo(Inspector), 34 - ), 35 - "t": NewTask, 36 37 "3": SwitchTo( 37 38 page: Todo(TaskList), 38 39 ), 39 - "shift-g": NewGroup, 40 40 "k": MoveUp, 41 41 }, 42 42 ), ··· 45 45 "tab": SwitchTo( 46 46 page: Zk, 47 47 ), 48 - "1": SwitchTo( 49 - page: Todo(Explorer), 50 - ), 48 + "p": EditPriority, 51 49 "n": EditName, 52 50 "3": SwitchTo( 53 51 page: Todo(TaskList), 54 52 ), 55 - "p": EditPriority, 56 53 "2": SwitchTo( 57 54 page: Todo(Inspector), 58 55 ), 56 + "1": SwitchTo( 57 + page: Todo(Explorer), 58 + ), 59 59 }, 60 60 ), 61 61 tasklist: ( 62 62 keybinds: { 63 - "k": MoveUp, 64 - "enter": SwitchTo( 65 - page: Todo(Inspector), 66 - ), 67 63 "tab": SwitchTo( 68 64 page: Zk, 69 65 ), ··· 73 69 "2": SwitchTo( 74 70 page: Todo(Inspector), 75 71 ), 76 - "j": MoveDown, 72 + "enter": SwitchTo( 73 + page: Todo(Inspector), 74 + ), 77 75 "1": SwitchTo( 78 76 page: Todo(Explorer), 79 77 ), 78 + "k": MoveUp, 79 + "j": MoveDown, 80 80 }, 81 81 ), 82 82 ),
+1
justfile
··· 21 21 cargo nextest r {{_cargo_flags}} 22 22 reset: 23 23 rm -rf ZettleKasten 24 + rm -rf ./.data 24 25 cargo run -- init 25 26 cargo run 26 27
+7 -4
src/tui/components/todo/mod.rs
··· 242 242 explorer.set_inactive(); 243 243 inspector.set_inactive(); 244 244 task_list.set_inactive(); 245 + 246 + inspector.register_signal_handler( 247 + self.signal_tx 248 + .clone() 249 + .expect("Must be initialized by this point"), 250 + )?; 251 + 245 252 self.explorer = Some(explorer); 246 253 self.task_list = Some(task_list); 247 254 self.inspector = Some(inspector); 248 255 249 - self.inspector 250 - .as_mut() 251 - .unwrap() 252 - .register_signal_handler(self.signal_tx.clone().unwrap())?; 253 256 Ok(()) 254 257 } 255 258
+3 -11
src/types/group.rs
··· 61 61 let _ = g 62 62 .into_active_model() 63 63 .set_name(new_name.as_str()) 64 - .save(&kt.db) 64 + .update(&kt.db) 65 65 .await?; 66 66 67 - TagEntity::load() 68 - .filter_by_nano_id(tag_id) 69 - .one(&kt.db) 70 - .await? 71 - .expect("Invariant Broken: Must exist") 72 - .into_active_model() 73 - .set_name(new_name.as_str()) 74 - .save(&kt.db) 75 - .await?; 67 + Tag::alter_name(tag_id, &new_name, kt).await?; 76 68 77 - Zettel::alter_name(zettel_id.into(), new_name, kt).await?; 69 + Zettel::alter_name(zettel_id.into(), &new_name, kt).await?; 78 70 79 71 Ok(()) 80 72 }
+42 -2
src/types/tag.rs
··· 1 - use dto::{NanoId, TagModel, TagModelEx}; 1 + use color_eyre::eyre::Result; 2 + use dto::{IntoActiveModel as _, NanoId, TagEntity, TagModel, TagModelEx, ZettelEntity}; 2 3 3 - use crate::types::Color; 4 + use crate::types::{Color, Kasten, Zettel}; 4 5 5 6 /// Represents a `Tag` in a `ZettelKasten` note taking method. 6 7 /// Easy way to link multiple notes under one simple word. ··· 15 16 pub name: String, 16 17 /// Color of the tag 17 18 pub color: Color, 19 + } 20 + 21 + impl Tag { 22 + pub async fn alter_name( 23 + id: NanoId, 24 + new_name: impl Into<String>, 25 + kt: &mut Kasten, 26 + ) -> Result<()> { 27 + let new_name = new_name.into(); 28 + 29 + TagEntity::load() 30 + .filter_by_nano_id(id.clone()) 31 + .one(&kt.db) 32 + .await? 33 + .expect("Invariant Broken: Must exist") 34 + .into_active_model() 35 + .set_name(new_name.as_str()) 36 + .update(&kt.db) 37 + .await?; 38 + 39 + // fetch all the zettels for this tag 40 + let tag = TagEntity::load() 41 + .filter_by_nano_id(id) 42 + .with(ZettelEntity) 43 + .one(&kt.db) 44 + .await? 45 + .expect("We just saved it"); 46 + 47 + assert!( 48 + tag.zettels.is_loaded(), 49 + "We expect the zettels to be loaded" 50 + ); 51 + 52 + for zettel in tag.zettels { 53 + Zettel::write_tags_from_db(zettel.nano_id.into(), kt).await?; 54 + } 55 + 56 + Ok(()) 57 + } 18 58 } 19 59 20 60 impl From<TagModel> for Tag {
+12
src/types/zettel/mod.rs
··· 75 75 Ok(()) 76 76 } 77 77 78 + /// Gets the tags from the database for this `Zettel` and write it to the file. 79 + pub async fn write_tags_from_db(id: ZettelId, kt: &mut Kasten) -> Result<()> { 80 + let zettel = Self::fetch_from_db(&id, &kt.db).await?.expect("must exist"); 81 + 82 + let file_path = zettel.absolute_path(&kt.index); 83 + let new_fm = FrontMatter::from(zettel); 84 + 85 + new_fm.flush_to_file(file_path)?; 86 + kt.index.process_zid(&id)?; 87 + Ok(()) 88 + } 89 + 78 90 pub async fn new(title: impl Into<String>, kt: &mut Kasten, tags: Vec<Tag>) -> Result<Self> { 79 91 // fn new(title: impl Into<String>) -> Result<Self> { 80 92 let title = title.into();
+7
src/viz/mod.rs
··· 104 104 self.filaments.set_links_for_zid(&zid, links); 105 105 } 106 106 107 + // this will refresh the entire screen, esentially spawning 108 + // in a new graph, maybe there is a better way to do this? 109 + // might be clean with conditional name-showing... 110 + Signal::Refresh => block_on(async { 111 + let index = &self.kh.read().await.index; 112 + self.filaments = Filaments::from(index); 113 + }), 107 114 _ => {} 108 115 } 109 116 }