diff --git a/api/justfile b/api/justfile index c0f0826..3bec780 100644 --- a/api/justfile +++ b/api/justfile @@ -1,11 +1,11 @@ generate_entities: - sea-orm-cli generate entity -u sqlite://../.data/storage.sqlite?mode=rwc -o orm/src/entities --entity-format dense + sea-orm-cli generate entity -u postgres://devuser:devpassword@localhost:5432/devdb -o orm/src/entities --entity-format dense generate_migration name: sea-orm-cli migrate generate {{ name }} reset_db: - sea-orm-cli migrate fresh -u sqlite://../.data/storage.sqlite?mode=rwc + sea-orm-cli migrate fresh -u postgres://devuser:devpassword@localhost:5432/devdb apply_migrations: - sea-orm-cli migrate up -u sqlite://../.data/storage.sqlite?mode=rwc + sea-orm-cli migrate up -u postgres://devuser:devpassword@localhost:5432/devdb diff --git a/api/migration/Cargo.toml b/api/migration/Cargo.toml index 24b4961..2713de1 100644 --- a/api/migration/Cargo.toml +++ b/api/migration/Cargo.toml @@ -9,7 +9,7 @@ name = "migration" path = "src/lib.rs" [features] -default = [] +default = ["postgres", "sqlite"] postgres = ["sea-orm-migration/sqlx-postgres"] sqlite = ["sea-orm-migration/sqlx-sqlite"] diff --git a/api/migration/src/m20260505_085735_add_todo_checks.rs b/api/migration/src/m20260505_085735_add_todo_checks.rs index 7905b86..7dcc0ca 100644 --- a/api/migration/src/m20260505_085735_add_todo_checks.rs +++ b/api/migration/src/m20260505_085735_add_todo_checks.rs @@ -1,4 +1,7 @@ -use sea_orm_migration::{prelude::*, schema::{uuid, date}}; +use sea_orm_migration::{ + prelude::*, + schema::{date, uuid}, +}; use crate::m20260504_125311_add_basic_todo_table::Todo; diff --git a/api/migration/src/m20260506_113244_add_todo_time.rs b/api/migration/src/m20260506_113244_add_todo_time.rs index 08f5a63..134dd79 100644 --- a/api/migration/src/m20260506_113244_add_todo_time.rs +++ b/api/migration/src/m20260506_113244_add_todo_time.rs @@ -1,4 +1,9 @@ -use sea_orm_migration::{prelude::*, schema::{date_null, date_time_null, enumeration, enumeration_null, integer_null, pk_uuid}, sea_orm::DatabaseBackend, sea_query::extension::postgres::Type}; +use sea_orm_migration::{ + prelude::*, + schema::{date_null, date_time_null, enumeration, enumeration_null, integer_null, pk_uuid}, + sea_orm::DatabaseBackend, + sea_query::extension::postgres::Type, +}; use crate::m20260504_125311_add_basic_todo_table::Todo; @@ -12,7 +17,7 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(Time::Format) + .as_enum("time_format") .values(["point", "range", "recurring"]) .to_owned(), ) @@ -21,7 +26,7 @@ impl MigrationTrait for Migration { manager .create_type( Type::create() - .as_enum(Time::RecurrenceMode) + .as_enum("recurrence_mode") .values(["daily", "weekly"]) .to_owned(), ) @@ -36,7 +41,7 @@ impl MigrationTrait for Migration { .col(pk_uuid(Time::TodoId)) .col(enumeration( Time::Format, - Time::Format, + "time_format", ["point", "range", "recurring"], )) .col(date_null(Time::DateStart)) @@ -44,7 +49,7 @@ impl MigrationTrait for Migration { .col(date_time_null(Time::DateTime)) .col(enumeration_null( Time::RecurrenceMode, - Time::RecurrenceMode, + "recurrence_mode", ["daily", "weekly"], )) .col(integer_null(Time::NumberStart)) diff --git a/api/migration/src/m20260508_075858_add_web_push_subscription.rs b/api/migration/src/m20260508_075858_add_web_push_subscription.rs index f8d83a3..b958e18 100644 --- a/api/migration/src/m20260508_075858_add_web_push_subscription.rs +++ b/api/migration/src/m20260508_075858_add_web_push_subscription.rs @@ -1,4 +1,7 @@ -use sea_orm_migration::{prelude::*, schema::{pk_auto, string}}; +use sea_orm_migration::{ + prelude::*, + schema::{pk_auto, string}, +}; #[derive(DeriveMigrationName)] pub struct Migration; diff --git a/api/migration/src/m20260525_164927_add_time_recurring_yearly.rs b/api/migration/src/m20260525_164927_add_time_recurring_yearly.rs index 4e92aeb..906e6a5 100644 --- a/api/migration/src/m20260525_164927_add_time_recurring_yearly.rs +++ b/api/migration/src/m20260525_164927_add_time_recurring_yearly.rs @@ -1,4 +1,9 @@ -use sea_orm_migration::{prelude::*, schema::{pk_uuid, enumeration, date_null, date_time_null, enumeration_null, integer_null}}; +use sea_orm_migration::{ + prelude::*, + schema::{date_null, date_time_null, enumeration, enumeration_null, integer_null, pk_uuid}, + sea_orm::DatabaseBackend, + sea_query::extension::postgres::Type, +}; use crate::{m20260504_125311_add_basic_todo_table::Todo, m20260506_113244_add_todo_time::Time}; @@ -8,6 +13,12 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + if manager.get_database_backend() == DatabaseBackend::Postgres { + manager + .alter_type(Type::alter().name("recurrence_mode").add_value("yearly")) + .await?; + } + manager .create_table( Table::create() @@ -16,7 +27,7 @@ impl MigrationTrait for Migration { .col(pk_uuid(TmpTime::TodoId)) .col(enumeration( TmpTime::Format, - TmpTime::Format, + "time_format", ["point", "range", "recurring"], )) .col(date_null(TmpTime::DateStart)) @@ -24,7 +35,7 @@ impl MigrationTrait for Migration { .col(date_time_null(TmpTime::DateTime)) .col(enumeration_null( TmpTime::RecurrenceMode, - TmpTime::RecurrenceMode, + "recurrence_mode", ["daily", "weekly", "yearly"], )) .col(integer_null(TmpTime::NumberStart)) diff --git a/api/migration/src/m20260529_073701_add_delete_time.rs b/api/migration/src/m20260529_073701_add_delete_time.rs index 6c194cb..44d3cc8 100644 --- a/api/migration/src/m20260529_073701_add_delete_time.rs +++ b/api/migration/src/m20260529_073701_add_delete_time.rs @@ -1,4 +1,4 @@ -use sea_orm_migration::{prelude::*, schema::timestamp_null}; +use sea_orm_migration::{prelude::*, schema::timestamp_with_time_zone_null}; use crate::{ m20260503_093223_add_tag_table::Tag, m20260503_125344_add_category_table::Category, @@ -15,7 +15,7 @@ impl MigrationTrait for Migration { .alter_table( Table::alter() .table(Todo::Table) - .add_column(timestamp_null(TodoDelete::Deleted)) + .add_column(timestamp_with_time_zone_null(TodoDelete::Deleted)) .to_owned(), ) .await?; @@ -24,7 +24,7 @@ impl MigrationTrait for Migration { .alter_table( Table::alter() .table(Tag::Table) - .add_column(timestamp_null(TagDelete::Deleted)) + .add_column(timestamp_with_time_zone_null(TagDelete::Deleted)) .to_owned(), ) .await?; @@ -33,7 +33,7 @@ impl MigrationTrait for Migration { .alter_table( Table::alter() .table(Category::Table) - .add_column(timestamp_null(CategoryDelete::Deleted)) + .add_column(timestamp_with_time_zone_null(CategoryDelete::Deleted)) .to_owned(), ) .await diff --git a/api/migration/src/m20260610_061458_add_todo_reminders.rs b/api/migration/src/m20260610_061458_add_todo_reminders.rs index b9ddca3..29af5a6 100644 --- a/api/migration/src/m20260610_061458_add_todo_reminders.rs +++ b/api/migration/src/m20260610_061458_add_todo_reminders.rs @@ -1,4 +1,9 @@ -use sea_orm_migration::{prelude::*, schema::{pk_auto, uuid, enumeration, date_time_null, integer_null}}; +use sea_orm_migration::{ + prelude::*, + schema::{date_time_null, enumeration, integer_null, pk_auto, uuid}, + sea_orm::DatabaseBackend, + sea_query::extension::postgres::Type, +}; use crate::m20260504_125311_add_basic_todo_table::Todo; @@ -8,6 +13,17 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + if manager.get_database_backend() == DatabaseBackend::Postgres { + manager + .create_type( + Type::create() + .as_enum("reminder_format") + .values(["time", "relative"]) + .to_owned(), + ) + .await?; + } + manager .create_table( Table::create() @@ -17,7 +33,7 @@ impl MigrationTrait for Migration { .col(uuid(Reminder::TodoId)) .col(enumeration( Reminder::Format, - Reminder::Format, + "reminder_format", ["time", "relative"], )) .col(date_time_null(Reminder::Time)) diff --git a/api/orm/src/entities/category.rs b/api/orm/src/entities/category.rs index 537312c..11ae9e2 100644 --- a/api/orm/src/entities/category.rs +++ b/api/orm/src/entities/category.rs @@ -12,7 +12,7 @@ pub struct Model { pub color: String, pub icon: String, pub owner_id: String, - pub deleted: Option, + pub deleted: Option, #[sea_orm(has_many)] pub todos: HasMany, } diff --git a/api/orm/src/entities/check.rs b/api/orm/src/entities/check.rs index 2f64997..14aadae 100644 --- a/api/orm/src/entities/check.rs +++ b/api/orm/src/entities/check.rs @@ -17,7 +17,7 @@ pub struct Model { on_update = "Cascade", on_delete = "Cascade" )] - pub todo: HasOne, + pub todo: BelongsTo, } impl ActiveModelBehavior for ActiveModel {} diff --git a/api/orm/src/entities/mod.rs b/api/orm/src/entities/mod.rs index d0eff40..692c24c 100644 --- a/api/orm/src/entities/mod.rs +++ b/api/orm/src/entities/mod.rs @@ -5,6 +5,7 @@ pub mod prelude; pub mod category; pub mod check; pub mod reminder; +pub mod sea_orm_active_enums; pub mod tag; pub mod time; pub mod todo; diff --git a/api/orm/src/entities/reminder.rs b/api/orm/src/entities/reminder.rs index 5e7687b..a02eb10 100644 --- a/api/orm/src/entities/reminder.rs +++ b/api/orm/src/entities/reminder.rs @@ -1,5 +1,6 @@ //! `SeaORM` Entity, @generated by sea-orm-codegen 2.0 +use super::sea_orm_active_enums::ReminderFormat; use sea_orm::entity::prelude::*; #[sea_orm::model] @@ -7,12 +8,11 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "reminder")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, + pub id: i32, pub todo_id: Uuid, - #[sea_orm(column_type = "Text")] - pub format: String, + pub format: ReminderFormat, pub time: Option, - pub offset: Option, + pub offset: Option, #[sea_orm( belongs_to, from = "todo_id", @@ -20,7 +20,7 @@ pub struct Model { on_update = "Cascade", on_delete = "Cascade" )] - pub todo: HasOne, + pub todo: BelongsTo, } impl ActiveModelBehavior for ActiveModel {} diff --git a/api/orm/src/entities/sea_orm_active_enums.rs b/api/orm/src/entities/sea_orm_active_enums.rs new file mode 100644 index 0000000..ded5de6 --- /dev/null +++ b/api/orm/src/entities/sea_orm_active_enums.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0 + +use sea_orm::entity::prelude::*; + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "Enum", db_type = "Enum", enum_name = "recurrence_mode")] +pub enum RecurrenceMode { + #[sea_orm(string_value = "daily")] + Daily, + #[sea_orm(string_value = "weekly")] + Weekly, + #[sea_orm(string_value = "yearly")] + Yearly, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "Enum", db_type = "Enum", enum_name = "reminder_format")] +pub enum ReminderFormat { + #[sea_orm(string_value = "time")] + Time, + #[sea_orm(string_value = "relative")] + Relative, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)] +#[sea_orm(rs_type = "Enum", db_type = "Enum", enum_name = "time_format")] +pub enum TimeFormat { + #[sea_orm(string_value = "point")] + Point, + #[sea_orm(string_value = "range")] + Range, + #[sea_orm(string_value = "recurring")] + Recurring, +} diff --git a/api/orm/src/entities/tag.rs b/api/orm/src/entities/tag.rs index 5ae277a..fc56401 100644 --- a/api/orm/src/entities/tag.rs +++ b/api/orm/src/entities/tag.rs @@ -11,7 +11,7 @@ pub struct Model { pub name: String, pub color: String, pub owner_id: String, - pub deleted: Option, + pub deleted: Option, #[sea_orm(has_many, via = "todo_tag")] pub todos: HasMany, } diff --git a/api/orm/src/entities/time.rs b/api/orm/src/entities/time.rs index d062056..b237fd9 100644 --- a/api/orm/src/entities/time.rs +++ b/api/orm/src/entities/time.rs @@ -1,5 +1,7 @@ //! `SeaORM` Entity, @generated by sea-orm-codegen 2.0 +use super::sea_orm_active_enums::RecurrenceMode; +use super::sea_orm_active_enums::TimeFormat; use sea_orm::entity::prelude::*; #[sea_orm::model] @@ -8,15 +10,13 @@ use sea_orm::entity::prelude::*; pub struct Model { #[sea_orm(primary_key, auto_increment = false)] pub todo_id: Uuid, - #[sea_orm(column_type = "Text")] - pub format: String, + pub format: TimeFormat, pub date_start: Option, pub date_end: Option, pub date_time: Option, - #[sea_orm(column_type = "Text", nullable)] - pub recurrence_mode: Option, - pub number_start: Option, - pub number_end: Option, + pub recurrence_mode: Option, + pub number_start: Option, + pub number_end: Option, #[sea_orm( belongs_to, from = "todo_id", @@ -24,7 +24,7 @@ pub struct Model { on_update = "Cascade", on_delete = "Cascade" )] - pub todo: HasOne, + pub todo: BelongsTo, } impl ActiveModelBehavior for ActiveModel {} diff --git a/api/orm/src/entities/todo.rs b/api/orm/src/entities/todo.rs index e479083..2c80d3a 100644 --- a/api/orm/src/entities/todo.rs +++ b/api/orm/src/entities/todo.rs @@ -12,8 +12,8 @@ pub struct Model { pub title: String, pub note: String, pub category_id: Option, - pub order: i64, - pub deleted: Option, + pub order: i32, + pub deleted: Option, #[sea_orm( belongs_to, from = "category_id", @@ -21,7 +21,7 @@ pub struct Model { on_update = "Cascade", on_delete = "SetNull" )] - pub category: HasOne, + pub category: BelongsTo>, #[sea_orm(has_many)] pub checks: HasMany, #[sea_orm(has_many)] diff --git a/api/orm/src/entities/todo_tag.rs b/api/orm/src/entities/todo_tag.rs index c363c54..5de3d07 100644 --- a/api/orm/src/entities/todo_tag.rs +++ b/api/orm/src/entities/todo_tag.rs @@ -17,7 +17,7 @@ pub struct Model { on_update = "Cascade", on_delete = "Cascade" )] - pub tag: HasOne, + pub tag: BelongsTo, #[sea_orm( belongs_to, from = "todo_id", @@ -25,7 +25,7 @@ pub struct Model { on_update = "Cascade", on_delete = "Cascade" )] - pub todo: HasOne, + pub todo: BelongsTo, } impl ActiveModelBehavior for ActiveModel {} diff --git a/api/orm/src/entities/web_push_subscription.rs b/api/orm/src/entities/web_push_subscription.rs index 030a837..289b928 100644 --- a/api/orm/src/entities/web_push_subscription.rs +++ b/api/orm/src/entities/web_push_subscription.rs @@ -7,7 +7,7 @@ use sea_orm::entity::prelude::*; #[sea_orm(table_name = "web_push_subscription")] pub struct Model { #[sea_orm(primary_key)] - pub id: i64, + pub id: i32, pub owner_id: String, pub endpoint: String, pub p256dh: String, diff --git a/api/orm/src/lib.rs b/api/orm/src/lib.rs index a3cb817..0f367e1 100644 --- a/api/orm/src/lib.rs +++ b/api/orm/src/lib.rs @@ -20,12 +20,6 @@ pub async fn init_db(url: &str) -> Result { let connection = Database::connect(options).await?; - let connection = match connection.get_database_backend() { - sea_orm::DatabaseBackend::Sqlite => connection, - sea_orm::DatabaseBackend::Postgres => connection, - _ => return Err(OrmError::UnsupportedBackend), - }; - Migrator::up(&connection, None).await?; Ok(connection) diff --git a/api/services/src/todos.rs b/api/services/src/todos.rs index a76e226..e8ed25e 100644 --- a/api/services/src/todos.rs +++ b/api/services/src/todos.rs @@ -2,8 +2,9 @@ use std::collections::HashSet; use chrono::{Duration, Local}; use orm::OrmConnection; +use orm::entities::sea_orm_active_enums::{RecurrenceMode, ReminderFormat, TimeFormat}; use sea_orm::ActiveValue::{NotSet, Set}; -use sea_orm::compound::HasOne::Loaded; +use sea_orm::compound::{BelongsTo, HasOne}; use sea_orm::sea_query::Expr; use sea_orm::{ ConnectionTrait, EntityTrait, ExprTrait, IntoActiveModel, ModelTrait, Order, QueryFilter, @@ -498,7 +499,7 @@ impl TodoService { user: &User, db: &T, todo: todo::Model, - target: i64, + target: i32, ) -> Result<(), sea_orm::DbErr> { let tx = db.begin().await?; @@ -521,34 +522,34 @@ impl TodoService { fn to_time_model(value: Time) -> time::ActiveModel { match value { Time::Range { inner } => time::ActiveModel { - format: Set("range".to_string()), + format: Set(TimeFormat::Range), date_start: Set(Some(inner.start)), date_end: Set(Some(inner.end)), ..Default::default() }, Time::Recurring { inner } => match inner { TimeRecurring::Daily {} => time::ActiveModel { - format: Set("recurring".to_string()), - recurrence_mode: Set(Some("daily".to_string())), + format: Set(TimeFormat::Recurring), + recurrence_mode: Set(Some(RecurrenceMode::Daily)), ..Default::default() }, TimeRecurring::Weekly { start, end } => time::ActiveModel { - format: Set("recurring".to_string()), - recurrence_mode: Set(Some("weekly".to_string())), + format: Set(TimeFormat::Recurring), + recurrence_mode: Set(Some(RecurrenceMode::Weekly)), number_start: Set(Some(start.cast_signed())), number_end: Set(Some(end.cast_signed())), ..Default::default() }, TimeRecurring::Yearly { month, day } => time::ActiveModel { - format: Set("recurring".to_string()), - recurrence_mode: Set(Some("yearly".to_string())), + format: Set(TimeFormat::Recurring), + recurrence_mode: Set(Some(RecurrenceMode::Yearly)), number_start: Set(Some(month.cast_signed())), number_end: Set(Some(day.cast_signed())), ..Default::default() }, }, Time::Point { inner } => time::ActiveModel { - format: Set("point".to_string()), + format: Set(TimeFormat::Point), date_time: Set(Some(inner.time.naive_utc())), ..Default::default() }, @@ -556,8 +557,8 @@ impl TodoService { } fn to_time_dto(value: &time::ModelEx) -> Result { - let time = match value.format.as_str() { - "range" => Time::Range { + let time = match value.format { + TimeFormat::Range => Time::Range { inner: TimeRange { start: value.date_start.ok_or(TodoServiceError::InvalidTime( "Required date_start not found".to_string(), @@ -567,56 +568,51 @@ impl TodoService { ))?, }, }, - "recurring" => match value - .recurrence_mode - .as_ref() - .ok_or(TodoServiceError::InvalidTime( - "Required recurrence_mode not found".to_string(), - ))? - .as_str() - { - "weekly" => Time::Recurring { - inner: TimeRecurring::Weekly { - start: value - .number_start - .ok_or(TodoServiceError::InvalidTime( - "Required number_start not found".to_string(), - ))? - .cast_unsigned(), - end: value - .number_end - .ok_or(TodoServiceError::InvalidTime( - "Required number_end not found".to_string(), - ))? - .cast_unsigned(), + TimeFormat::Recurring => { + match value + .recurrence_mode + .as_ref() + .ok_or(TodoServiceError::InvalidTime( + "Required recurrence_mode not found".to_string(), + ))? { + RecurrenceMode::Weekly => Time::Recurring { + inner: TimeRecurring::Weekly { + start: value + .number_start + .ok_or(TodoServiceError::InvalidTime( + "Required number_start not found".to_string(), + ))? + .cast_unsigned(), + end: value + .number_end + .ok_or(TodoServiceError::InvalidTime( + "Required number_end not found".to_string(), + ))? + .cast_unsigned(), + }, }, - }, - "daily" => Time::Recurring { - inner: TimeRecurring::Daily {}, - }, - "yearly" => Time::Recurring { - inner: TimeRecurring::Yearly { - month: value - .number_start - .ok_or(TodoServiceError::InvalidTime( - "Required number_start not found".to_string(), - ))? - .cast_unsigned(), - day: value - .number_end - .ok_or(TodoServiceError::InvalidTime( - "Required number_end not found".to_string(), - ))? - .cast_unsigned(), + RecurrenceMode::Daily => Time::Recurring { + inner: TimeRecurring::Daily {}, + }, + RecurrenceMode::Yearly => Time::Recurring { + inner: TimeRecurring::Yearly { + month: value + .number_start + .ok_or(TodoServiceError::InvalidTime( + "Required number_start not found".to_string(), + ))? + .cast_unsigned(), + day: value + .number_end + .ok_or(TodoServiceError::InvalidTime( + "Required number_end not found".to_string(), + ))? + .cast_unsigned(), + }, }, - }, - mode => { - return Err(TodoServiceError::InvalidTime(format!( - "unknown recurrence mode: {mode}" - ))); } - }, - "point" => Time::Point { + } + TimeFormat::Point => Time::Point { inner: TimePoint { time: value .date_time @@ -626,11 +622,6 @@ impl TodoService { .and_utc(), }, }, - format => { - return Err(TodoServiceError::InvalidTime(format!( - "unknown time format: {format}" - ))); - } }; Ok(time) @@ -664,12 +655,12 @@ impl TodoService { } }) .collect::>(); - let time = if let Loaded(Some(time)) = todo.time.clone() { + let time = if let HasOne::Loaded(Some(time)) = todo.time.clone() { Some(Self::to_time_dto(&time)?) } else { None }; - let category = if let Loaded(Some(category)) = todo.category.clone() { + let category = if let BelongsTo::Loaded(Some(category)) = todo.category.clone() { Some(to_category_dto(&category)?) } else { None @@ -690,12 +681,12 @@ impl TodoService { fn to_reminder_model(value: Reminder) -> reminder::ActiveModel { match value { Reminder::Time { inner } => reminder::ActiveModel { - format: Set("time".to_string()), + format: Set(ReminderFormat::Time), time: Set(Some(inner.time.naive_utc())), ..Default::default() }, Reminder::Relative { inner } => reminder::ActiveModel { - format: Set("relative".to_string()), + format: Set(ReminderFormat::Relative), offset: Set(Some(inner.offset)), ..Default::default() }, @@ -703,8 +694,8 @@ impl TodoService { } fn to_reminder_dto(value: &reminder::ModelEx) -> Result { - let reminder = match value.format.as_str() { - "time" => Reminder::Time { + let reminder = match value.format { + ReminderFormat::Time => Reminder::Time { inner: ReminderTime { time: value .time @@ -714,18 +705,13 @@ impl TodoService { .and_utc(), }, }, - "relative" => Reminder::Relative { + ReminderFormat::Relative => Reminder::Relative { inner: ReminderRelative { offset: value.offset.ok_or(TodoServiceError::InvalidReminder( "Required offset not found".to_string(), ))?, }, }, - format => { - return Err(TodoServiceError::InvalidReminder(format!( - "unknown reminder format: {format}" - ))); - } }; Ok(reminder) diff --git a/api/services/src/webpush.rs b/api/services/src/webpush.rs index 9d92cba..70ae308 100644 --- a/api/services/src/webpush.rs +++ b/api/services/src/webpush.rs @@ -68,7 +68,7 @@ impl WebPushService { Ok(result.is_some()) } - pub async fn delete_by_id(db: &DatabaseConnection, id: i64) -> Result<(), WebPushServiceError> { + pub async fn delete_by_id(db: &DatabaseConnection, id: i32) -> Result<(), WebPushServiceError> { web_push_subscription::Entity::delete_by_id(id) .exec(db) .await?; @@ -78,7 +78,7 @@ impl WebPushService { pub async fn get_all_by_owner_id( db: &DatabaseConnection, owner: &str, - ) -> Result, WebPushServiceError> { + ) -> Result, WebPushServiceError> { let subscriptions = web_push_subscription::Entity::find() .filter(web_push_subscription::COLUMN.owner_id.eq(owner)) .all(db) diff --git a/api/src/jobs/web_push_notifications.rs b/api/src/jobs/web_push_notifications.rs index 865bc40..da7eba8 100644 --- a/api/src/jobs/web_push_notifications.rs +++ b/api/src/jobs/web_push_notifications.rs @@ -95,7 +95,7 @@ fn is_in_time_window( continue; }; - let offset = Duration::from_mins(inner.offset.unsigned_abs()); + let offset = Duration::from_mins(u64::from(inner.offset.unsigned_abs())); let time = if inner.offset >= 0 { time.time - offset } else { @@ -103,7 +103,7 @@ fn is_in_time_window( }; if &time > start && &time < end { - return Some(TimeInterval::Reminder(inner.offset)); + return Some(TimeInterval::Reminder(i64::from(inner.offset))); } } } diff --git a/flake.lock b/flake.lock index 4031002..a2b5752 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1785318670, - "narHash": "sha256-dN6Ou5x/+23FZLEpYP3IffO+NyJFzUlGumt1uu3MMaY=", + "lastModified": 1787135253, + "narHash": "sha256-RD2kNWCG+Bjo6h+JVjWVNntZs2GtRoeY2xHjts/FNkA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0954f7ee2f6bb3dc7d4e3d0d8bcb8fd4bde4cfc5", + "rev": "ffb3c9b700e759be2ef13237c9d8f953b32a1e46", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 0eaa470..d776710 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ packages = [ pkgs.pkg-config pkgs.openssl + pkgs.sea-orm-cli ]; }; diff --git a/libs/types/src/todo/reminder.rs b/libs/types/src/todo/reminder.rs index 7dd2375..ce64cd9 100644 --- a/libs/types/src/todo/reminder.rs +++ b/libs/types/src/todo/reminder.rs @@ -24,5 +24,5 @@ pub struct ReminderTime { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct ReminderRelative { - pub offset: i64, + pub offset: i32, } diff --git a/libs/types/src/todo/time.rs b/libs/types/src/todo/time.rs index 8b8fd61..c221f22 100644 --- a/libs/types/src/todo/time.rs +++ b/libs/types/src/todo/time.rs @@ -16,11 +16,11 @@ pub struct TimeRange { pub end: NaiveDate, } -const fn default_start() -> u64 { +const fn default_start() -> u32 { 6 } -const fn default_end() -> u64 { +const fn default_end() -> u32 { 0 } @@ -33,17 +33,17 @@ pub enum TimeRecurring { #[serde(rename = "weekly")] Weekly { #[serde(default = "default_start")] - start: u64, + start: u32, #[serde(default = "default_end")] - end: u64, + end: u32, }, #[serde(rename = "yearly")] Yearly { #[serde(default = "default_start")] - month: u64, + month: u32, #[serde(default = "default_end")] - day: u64, + day: u32, }, } @@ -86,20 +86,16 @@ impl Time { let now = chrono::Local::now(); TimeRange { - start: now.add(Days::new(*start)).date_naive(), - end: now.add(Days::new(*end)).date_naive(), + start: now.add(Days::new(u64::from(*start))).date_naive(), + end: now.add(Days::new(u64::from(*end))).date_naive(), } } TimeRecurring::Yearly { month, day } => { let now = chrono::Local::now().date_naive(); let year = now.year(); - let date = chrono::NaiveDate::from_ymd_opt( - year, - u32::try_from(*month).map_err(|_| TodoError::InvalidTimeRange)?, - u32::try_from(*day).map_err(|_| TodoError::InvalidTimeRange)?, - ) - .ok_or(TodoError::InvalidTimeRange)?; + let date = chrono::NaiveDate::from_ymd_opt(year, *month, *day) + .ok_or(TodoError::InvalidTimeRange)?; TimeRange { start: date,