modularize date, database, and model code
- Add reusable date parsing, formatting, and recurrence modules - Split database import helpers and model types into focused modules - Expose the application as a library for the binary
This commit is contained in:
268
src/model.rs
268
src/model.rs
@@ -1,254 +1,16 @@
|
||||
use std::{fmt, str::FromStr};
|
||||
mod category;
|
||||
mod enums;
|
||||
mod item;
|
||||
mod macro_def;
|
||||
mod settings;
|
||||
mod view;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Item {
|
||||
pub id: i64,
|
||||
pub text: String,
|
||||
pub note: String,
|
||||
pub priority: i64,
|
||||
pub when_at: Option<String>,
|
||||
pub done_at: Option<String>,
|
||||
pub alarm_at: Option<String>,
|
||||
pub numeric_value: Option<f64>,
|
||||
pub recurrence: String,
|
||||
pub created_at: String,
|
||||
pub updated_at: String,
|
||||
pub discarded: bool,
|
||||
pub categories: Vec<Category>,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn category_names(&self) -> String {
|
||||
self.categories
|
||||
.iter()
|
||||
.map(|c| c.name.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Category {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub parent_id: Option<i64>,
|
||||
pub kind: CategoryKind,
|
||||
pub match_text: String,
|
||||
pub exclusive: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ViewDef {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub kind: ViewKind,
|
||||
pub filter_value: String,
|
||||
pub sort_key: SortKey,
|
||||
pub show_done: bool,
|
||||
pub filter_expr: String,
|
||||
pub columns: Vec<ViewColumn>,
|
||||
pub sections: Vec<ViewSection>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ViewColumn {
|
||||
pub field: String,
|
||||
pub heading: String,
|
||||
pub width: u16,
|
||||
pub aggregate: Aggregate,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ViewSection {
|
||||
pub id: i64,
|
||||
pub heading: String,
|
||||
pub filter_expr: String,
|
||||
pub collapsed: bool,
|
||||
}
|
||||
|
||||
impl ViewDef {
|
||||
pub fn columns_spec(&self) -> String {
|
||||
self.columns
|
||||
.iter()
|
||||
.map(|c| format!("{}:{}:{}:{}", c.field, c.width, c.heading, c.aggregate))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
}
|
||||
pub fn sections_spec(&self) -> String {
|
||||
self.sections
|
||||
.iter()
|
||||
.map(|s| {
|
||||
format!(
|
||||
"{}|{}{}",
|
||||
s.heading,
|
||||
s.filter_expr,
|
||||
if s.collapsed { "|collapsed" } else { "" }
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(";")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct CategoryRule {
|
||||
pub id: i64,
|
||||
pub category_id: i64,
|
||||
pub condition_expr: String,
|
||||
pub action_kind: RuleActionKind,
|
||||
pub action_value: String,
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MacroDef {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub source: String,
|
||||
pub key_binding: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ItemChanges {
|
||||
pub text: Option<String>,
|
||||
pub note: Option<String>,
|
||||
pub priority: Option<i64>,
|
||||
pub when_at: Option<Option<String>>,
|
||||
pub alarm_at: Option<Option<String>>,
|
||||
pub numeric_value: Option<Option<f64>>,
|
||||
pub recurrence: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DocumentSettings {
|
||||
pub description: String,
|
||||
pub backup_on_open: bool,
|
||||
pub trash_policy: TrashPolicy,
|
||||
pub done_policy: DonePolicy,
|
||||
pub automatic_filing: bool,
|
||||
pub date_order: DateOrder,
|
||||
pub week_start: WeekStart,
|
||||
pub default_time: String,
|
||||
pub morning_time: String,
|
||||
pub afternoon_time: String,
|
||||
pub evening_time: String,
|
||||
pub note_tab_width: u8,
|
||||
}
|
||||
|
||||
impl Default for DocumentSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
description: String::new(),
|
||||
backup_on_open: false,
|
||||
trash_policy: TrashPolicy::OnDemand,
|
||||
done_policy: DonePolicy::Keep,
|
||||
automatic_filing: true,
|
||||
date_order: DateOrder::YearMonthDay,
|
||||
week_start: WeekStart::Monday,
|
||||
default_time: "09:00".into(),
|
||||
morning_time: "09:00".into(),
|
||||
afternoon_time: "13:00".into(),
|
||||
evening_time: "18:00".into(),
|
||||
note_tab_width: 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
macro_rules! string_enum {
|
||||
($name:ident { $($variant:ident => $value:literal),+ $(,)? }) => {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum $name {
|
||||
$($variant),+
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub const fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
$(Self::$variant => $value),+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for $name {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for $name {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
$($value => Ok(Self::$variant),)+
|
||||
_ => Err(format!("unsupported {} {value:?}", stringify!($name))),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
string_enum!(CategoryKind {
|
||||
Standard => "standard",
|
||||
Date => "date",
|
||||
Numeric => "numeric",
|
||||
});
|
||||
|
||||
string_enum!(ViewKind {
|
||||
List => "list",
|
||||
Category => "category",
|
||||
Upcoming => "upcoming",
|
||||
Done => "done",
|
||||
Datebook => "datebook",
|
||||
Trash => "trash",
|
||||
});
|
||||
|
||||
string_enum!(SortKey {
|
||||
Manual => "manual",
|
||||
When => "when",
|
||||
Done => "done",
|
||||
Priority => "priority",
|
||||
Updated => "updated",
|
||||
});
|
||||
|
||||
string_enum!(Aggregate {
|
||||
None => "none",
|
||||
Sum => "sum",
|
||||
Average => "avg",
|
||||
Count => "count",
|
||||
Minimum => "min",
|
||||
Maximum => "max",
|
||||
});
|
||||
|
||||
string_enum!(RuleActionKind {
|
||||
Assign => "assign",
|
||||
Exclude => "exclude",
|
||||
Priority => "priority",
|
||||
Value => "value",
|
||||
When => "when",
|
||||
Alarm => "alarm",
|
||||
Repeat => "repeat",
|
||||
Done => "done",
|
||||
});
|
||||
|
||||
string_enum!(TrashPolicy {
|
||||
OnDemand => "on-demand",
|
||||
OnClose => "on-close",
|
||||
EndOfDay => "end-of-day",
|
||||
Immediate => "immediate",
|
||||
});
|
||||
|
||||
string_enum!(DonePolicy {
|
||||
Keep => "keep",
|
||||
Trash => "trash",
|
||||
});
|
||||
|
||||
string_enum!(DateOrder {
|
||||
YearMonthDay => "ymd",
|
||||
MonthDayYear => "mdy",
|
||||
DayMonthYear => "dmy",
|
||||
});
|
||||
|
||||
string_enum!(WeekStart {
|
||||
Monday => "monday",
|
||||
Sunday => "sunday",
|
||||
});
|
||||
pub use category::{Category, CategoryRule};
|
||||
pub use enums::{
|
||||
Aggregate, CategoryKind, DateOrder, DonePolicy, RuleActionKind, SortKey, TrashPolicy, ViewKind,
|
||||
WeekStart,
|
||||
};
|
||||
pub use item::{Item, ItemChanges};
|
||||
pub use macro_def::MacroDef;
|
||||
pub use settings::DocumentSettings;
|
||||
pub use view::{ViewColumn, ViewDef, ViewSection};
|
||||
|
||||
Reference in New Issue
Block a user