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: created application types

+240
+4
crates/dto/migration/src/m20260319_002245_task_table.rs
··· 31 31 .default(Priority::default().to_string()), 32 32 ) 33 33 .col(timestamp(Task::Due).null()) 34 + .col(timestamp(Task::FinishedAt).null()) 34 35 .col(timestamp(Task::CreatedAt).default(Expr::current_timestamp())) 35 36 .col(timestamp(Task::ModifiedAt).default(Expr::current_timestamp())) 36 37 .col(string(Task::ZettelId).not_null().unique_key()) ··· 131 132 132 133 /// The duedate for this task 133 134 Due, 135 + 136 + /// Completion time 137 + FinishedAt, 134 138 135 139 /// Creation time 136 140 CreatedAt,
+1
crates/dto/src/entity/task.rs
··· 17 17 pub name: String, 18 18 pub priority: Priority, 19 19 pub due: Option<DateTimeUtc>, 20 + pub finished_at: Option<DateTimeUtc>, 20 21 pub created_at: DateTimeUtc, 21 22 pub modified_at: DateTimeUtc, 22 23 #[sea_orm(unique)]
+6
crates/dto/src/lib.rs
··· 5 5 mod db; 6 6 pub use db::*; 7 7 8 + /// For database stuff 9 + pub use migration::{Migrator, MigratorTrait}; 10 + pub use sea_orm::{Database, DatabaseConnection}; 11 + 8 12 /// exported traits for the database 9 13 pub use sea_orm::ActiveModelTrait; 10 14 pub use sea_orm::ActiveValue; ··· 14 18 /// Exporting this as DTO so we can newtype this in a later crate 15 19 /// and add additional functionality to it. 16 20 pub use migration::types::Priority as PriorityDTO; 21 + 22 + pub use sea_orm::entity::prelude::DateTimeUtc; 17 23 18 24 /// Color type, exporting as DTO because I might 19 25 /// want to newtype wrap this, might not have to, depending
+1
src/main.rs
··· 13 13 mod cli; 14 14 mod gui; 15 15 mod tui; 16 + mod types; 16 17 17 18 mod config; 18 19 mod errors;
+13
src/types/color.rs
··· 1 + use dto::ColorDTO; 2 + 3 + /// Agnostic Color type, 4 + /// internally represented as rgb 5 + #[expect(dead_code)] 6 + #[derive(Debug, Clone)] 7 + pub struct Color(ColorDTO); 8 + 9 + impl From<ColorDTO> for Color { 10 + fn from(value: ColorDTO) -> Self { 11 + Self(value) 12 + } 13 + }
+43
src/types/group.rs
··· 1 + use dto::{DateTimeUtc, GroupModelEx, NanoId}; 2 + 3 + use crate::types::{Color, Priority, Zettel}; 4 + 5 + /// A `Group` which contains tasks! 6 + #[expect(dead_code)] 7 + #[derive(Debug, Clone)] 8 + pub struct Group { 9 + /// Should only be constructed from models. 10 + _private: (), 11 + 12 + pub id: NanoId, 13 + pub name: String, 14 + pub color: Color, 15 + pub priority: Priority, 16 + pub created_at: DateTimeUtc, 17 + pub modified_at: DateTimeUtc, 18 + /// The `Zettel` that is related to this `Group`. 19 + /// Can store notes regarding this group in 20 + /// the `Zettel` 21 + pub zettel: Zettel, 22 + } 23 + 24 + impl From<GroupModelEx> for Group { 25 + fn from(value: GroupModelEx) -> Self { 26 + Self { 27 + _private: (), 28 + id: value.nano_id, 29 + name: value.name, 30 + color: value.color.into(), 31 + priority: value.priority.into(), 32 + created_at: value.created_at, 33 + modified_at: value.modified_at, 34 + zettel: value 35 + .zettel 36 + .into_option() 37 + .expect( 38 + "When fetching a Group from the database, we expect to always have the Zettel loaded!!", 39 + ) 40 + .into(), 41 + } 42 + } 43 + }
+22
src/types/mod.rs
··· 1 + mod color; 2 + pub use color::Color; 3 + 4 + mod tag; 5 + pub use tag::Tag; 6 + 7 + mod priority; 8 + pub use priority::Priority; 9 + 10 + mod zettel; 11 + pub use zettel::Zettel; 12 + 13 + mod group; 14 + pub use group::Group; 15 + 16 + mod task; 17 + #[expect(unused_imports)] 18 + pub use task::Task; 19 + 20 + mod workspace; 21 + #[expect(unused_imports)] 22 + pub use workspace::Workspace;
+13
src/types/priority.rs
··· 1 + use dto::PriorityDTO; 2 + 3 + /// An Enum for the various `Priority` levels 4 + /// for `Task`s and `Group`s 5 + #[expect(dead_code)] 6 + #[derive(Debug, Clone)] 7 + pub struct Priority(PriorityDTO); 8 + 9 + impl From<PriorityDTO> for Priority { 10 + fn from(value: PriorityDTO) -> Self { 11 + Self(value) 12 + } 13 + }
+41
src/types/tag.rs
··· 1 + use dto::{NanoId, TagModel, TagModelEx}; 2 + 3 + use crate::types::Color; 4 + 5 + /// Represents a `Tag` in a `ZettelKasten` note taking method. 6 + /// Easy way to link multiple notes under one simple word. 7 + #[expect(dead_code)] 8 + #[derive(Debug, Clone)] 9 + pub struct Tag { 10 + /// Should only be constructed from models. 11 + _private: (), 12 + 13 + /// A unique `NanoId` 14 + pub id: NanoId, 15 + /// Name of the tag 16 + pub name: String, 17 + /// Color of the tag 18 + pub color: Color, 19 + } 20 + 21 + impl From<TagModel> for Tag { 22 + fn from(value: TagModel) -> Self { 23 + Self { 24 + _private: (), 25 + id: value.nano_id, 26 + name: value.name, 27 + color: value.color.into(), 28 + } 29 + } 30 + } 31 + 32 + impl From<TagModelEx> for Tag { 33 + fn from(value: TagModelEx) -> Self { 34 + Self { 35 + _private: (), 36 + id: value.nano_id, 37 + name: value.name, 38 + color: value.color.into(), 39 + } 40 + } 41 + }
+52
src/types/task.rs
··· 1 + use dto::{DateTimeUtc, NanoId, TaskModelEx}; 2 + 3 + use crate::types::{Group, Priority, Zettel}; 4 + 5 + /// a `Task` that you have to complete! 6 + #[expect(dead_code)] 7 + #[derive(Debug, Clone)] 8 + pub struct Task { 9 + /// Should only be constructed from models. 10 + _private:(), 11 + 12 + pub id: NanoId, 13 + pub name: String, 14 + pub priority: Priority, 15 + pub due: Option<DateTimeUtc>, 16 + pub finished_at: Option<DateTimeUtc>, 17 + pub created_at: DateTimeUtc, 18 + pub modified_at: DateTimeUtc, 19 + /// Each task has its own related `Zettel`. 20 + pub zettel: Zettel, 21 + pub group: Group, 22 + } 23 + 24 + impl From<TaskModelEx> for Task { 25 + fn from(value: TaskModelEx) -> Self { 26 + Self { 27 + _private: (), 28 + id: value.nano_id, 29 + name: value.name, 30 + priority: value.priority.into(), 31 + due: value.due, 32 + finished_at: value.finished_at, 33 + created_at: value.created_at, 34 + modified_at: value.modified_at, 35 + zettel: value 36 + .zettel 37 + .into_option() 38 + .expect( 39 + "When fetching a Task from the database, we expect to always have the Zettel loaded!!", 40 + ) 41 + .into(), 42 + group: value 43 + .group 44 + .into_option() 45 + .expect( 46 + "When fetching a Task from the database, we expect to always have the Group loaded!!", 47 + ) 48 + .into(), 49 + 50 + } 51 + } 52 + }
+5
src/types/workspace.rs
··· 1 + use dto::DatabaseConnection; 2 + 3 + pub struct Workspace { 4 + db: DatabaseConnection, 5 + }
+39
src/types/zettel.rs
··· 1 + use std::path::PathBuf; 2 + 3 + use dto::{NanoId, ZettelModelEx}; 4 + 5 + use crate::types::Tag; 6 + 7 + /// A `Zettel` is a note about a single idea. 8 + /// It can have many `Tag`s, just meaning it can fall under many 9 + /// categories. 10 + #[expect(dead_code)] 11 + #[derive(Debug, Clone)] 12 + pub struct Zettel { 13 + /// Should only be constructed from models. 14 + _private: (), 15 + 16 + pub id: NanoId, 17 + pub title: String, 18 + /// a workspace-local file path, needs to be canonicalized before usage 19 + pub file_path: PathBuf, 20 + pub tags: Vec<Tag>, 21 + } 22 + 23 + impl From<ZettelModelEx> for Zettel { 24 + fn from(value: ZettelModelEx) -> Self { 25 + assert!( 26 + !value.tags.is_unloaded(), 27 + "When fetching a Zettel from the database, we expect 28 + to always have the tags loaded!!" 29 + ); 30 + 31 + Self { 32 + _private: (), 33 + id: value.nano_id, 34 + title: value.title, 35 + file_path: value.file_path.into(), 36 + tags: value.tags.into_iter().map(Into::into).collect(), 37 + } 38 + } 39 + }