···11use clap::{Parser, Subcommand};
22+use dto::NanoId;
2334use crate::config::{get_config_dir, get_data_dir};
45···2930 #[command(subcommand)]
3031 Zettel(ZettelSubcommand),
31323333+ #[command(subcommand)]
3434+ Todo(TodoSubcommand),
3535+3236 /// Spawn the `LSP`
3337 Lsp,
3438···5862}
59636064#[derive(Subcommand, Debug)]
6161-/// Subcommand to manage tars groups.
6565+/// Subcommand to manage Zettels.
6266pub enum ZettelSubcommand {
6367 /// Add a group.
6468 New {
···7175 /// Filter by tag
7276 #[arg(short = 't', long)]
7377 by_tag: String,
7878+ },
7979+}
8080+8181+#[derive(Subcommand, Debug)]
8282+/// Subcommand to manage To-Do functionality
8383+pub enum TodoSubcommand {
8484+ Group {
8585+ /// The name of this group
8686+ #[arg(short, long)]
8787+ name: String,
8888+8989+ /// If this group has a parent, provide the parent id.
9090+ #[arg(short, long)]
9191+ parent_id: Option<NanoId>,
7492 },
7593}
7694
+64-2
src/cli/process.rs
···55};
6677use color_eyre::eyre::{Context, Result};
88+use dto::{
99+ GroupActiveModel, GroupEntity, IntoActiveModel, TagActiveModel, TagEntity, ZettelEntity,
1010+};
811use tower_lsp::{LspService, Server};
9121013use crate::{
1114 cli::{Commands, ZettelSubcommand},
1215 config::{Config, get_config_dir},
1316 lsp::Backend,
1414- types::{Kasten, Zettel},
1717+ types::{Group, Kasten, Priority, Tag, Zettel},
1518};
16191720impl Commands {
···50535154 match zettel_sub_command {
5255 ZettelSubcommand::New { title } => {
5353- let zettel = Zettel::new(title, &mut kt).await?;
5656+ let zettel = Zettel::new(title, &mut kt, vec![]).await?;
5457 println!("Zettel Created! {zettel:#?}");
5558 }
5659 ZettelSubcommand::List { by_tag: _by_tag } => {}
···6871 let (service, socket) = LspService::new(|client| Backend::new(client, kt));
69727073 Server::new(stdin, stdout, socket).serve(service).await;
7474+ }
7575+7676+ Self::Todo(command) => {
7777+ let conf = Config::parse()?;
7878+ let mut kt = Kasten::instansiate(conf.fil_dir).await?;
7979+8080+ match command {
8181+ super::TodoSubcommand::Group { name, parent_id } => {
8282+ // lets create a tag for this first group first
8383+8484+ let tag: Tag = TagActiveModel::builder()
8585+ .set_name(name.clone())
8686+ .insert(&kt.db)
8787+ .await?
8888+ .into();
8989+9090+ //TODO: this zettel would need to be created with the parent of all
9191+ // of its groups?
9292+ let tag_id = tag.id.clone();
9393+9494+ let zettel = Zettel::new(name.clone(), &mut kt, vec![tag]).await?;
9595+9696+ let inserted = GroupActiveModel::builder()
9797+ .set_name(name)
9898+ .set_parent_group_id(parent_id)
9999+ .set_tag(
100100+ TagEntity::load()
101101+ .filter_by_nano_id(tag_id)
102102+ .one(&kt.db)
103103+ .await?
104104+ .expect("Tag must exist since we just created it")
105105+ .into_active_model(),
106106+ )
107107+ .set_zettel(
108108+ ZettelEntity::load()
109109+ // .with(TagEntity)
110110+ .filter_by_nano_id(zettel.id)
111111+ .one(&kt.db)
112112+ .await?
113113+ .expect("Zettel must exist since we just created it")
114114+ .into_active_model(),
115115+ )
116116+ .set_priority(Priority::default())
117117+ .insert(&kt.db)
118118+ .await?;
119119+120120+ // group should also have the accompanying tag for it.
121121+ let group: Group = GroupEntity::load()
122122+ .with(TagEntity)
123123+ .with((ZettelEntity, TagEntity))
124124+ .filter_by_nano_id(inserted.nano_id)
125125+ .one(&kt.db)
126126+ .await?
127127+ .expect("We just inserted it")
128128+ .into();
129129+130130+ println!("created group {group:#?}");
131131+ }
132132+ }
71133 }
72134 }
73135
+2-2
src/tui/components/zk/mod.rs
···7272 let mut zettels: Vec<Zettel> = fetch_all().await?;
73737474 if zettels.is_empty() {
7575- let _ = Zettel::new("Welcome!", &mut *kh.write().await).await?;
7575+ let _ = Zettel::new("Welcome!", &mut *kh.write().await, vec![]).await?;
7676 zettels = fetch_all().await?;
7777 }
7878···236236 let mut kt = self.kh.write().await;
237237238238 // we create the zettel with the query as the
239239- let z = Zettel::new(self.search.query(), &mut kt)
239239+ let z = Zettel::new(self.search.query(), &mut kt, vec![])
240240 .await
241241 .with_context(|| "Failed to create a new Zettel!")?;
242242
+11-3
src/types/group.rs
···11use dto::{DateTime, GroupModelEx, NanoId};
2233-use crate::types::{Color, Priority, Zettel};
33+use crate::types::{Priority, Tag, Zettel};
4455/// A `Group` which contains tasks!
66#[expect(dead_code)]
···11111212 pub id: NanoId,
1313 pub name: String,
1414- pub color: Color,
1514 pub priority: Priority,
1615 pub created_at: DateTime,
1716 pub modified_at: DateTime,
···1918 /// Can store notes regarding this group in
2019 /// the `Zettel`
2120 pub zettel: Zettel,
2121+2222+ /// The `Tag` that is related to this `Group`
2323+ pub tag: Tag,
2224}
23252426impl From<GroupModelEx> for Group {
···2729 _private: (),
2830 id: value.nano_id,
2931 name: value.name,
3030- color: value.color.into(),
3132 priority: value.priority.into(),
3233 created_at: value.created_at,
3334 modified_at: value.modified_at,
···3839 "When fetching a Group from the database, we expect to always have the Zettel loaded!!",
3940 )
4041 .into(),
4242+ tag: value
4343+ .tag
4444+ .into_option()
4545+ .expect(
4646+ "When fetching a Group from the database, we expect to always have the Zettel loaded!!",
4747+ )
4848+ .into(),
4149 }
4250 }
4351}
+11-4
src/types/priority.rs
···2233/// An Enum for the various `Priority` levels
44/// for `Task`s and `Group`s
55-#[expect(dead_code)]
66-#[derive(Debug, Clone)]
77-pub struct Priority(PriorityDTO);
55+#[derive(Debug, Clone, Default)]
66+pub struct Priority {
77+ field1: PriorityDTO,
88+}
89910impl From<PriorityDTO> for Priority {
1011 fn from(value: PriorityDTO) -> Self {
1111- Self(value)
1212+ Self { field1: value }
1313+ }
1414+}
1515+1616+impl From<Priority> for PriorityDTO {
1717+ fn from(value: Priority) -> Self {
1818+ value.field1
1219 }
1320}
+17-6
src/types/zettel/mod.rs
···4141 .map(Into::into))
4242 }
43434444- pub async fn new(title: impl Into<String>, kt: &mut Kasten) -> Result<Self> {
4444+ pub async fn new(title: impl Into<String>, kt: &mut Kasten, tags: Vec<Tag>) -> Result<Self> {
4545 // fn new(title: impl Into<String>) -> Result<Self> {
4646 let title = title.into();
4747···6060 format!("Failed to create file at local file path: {local_file_path}")
6161 })?;
62626363- let inserted = ZettelActiveModel::builder()
6464- .set_title(title.clone())
6565- .set_nano_id(nano_id)
6666- .insert(&kt.db)
6767- .await?;
6363+ let inserted = {
6464+ let mut am = ZettelActiveModel::builder()
6565+ .set_title(title.clone())
6666+ .set_nano_id(nano_id);
6767+6868+ for tag in tags {
6969+ let tag = TagEntity::load()
7070+ .filter_by_nano_id(tag.id)
7171+ .one(&kt.db)
7272+ .await?
7373+ .expect("Invariant broken, tag must exist");
7474+ am = am.add_tag(tag);
7575+ }
7676+7777+ am.insert(&kt.db).await?
7878+ };
68796980 // need to load tags...
7081 let zettel = ZettelEntity::load()