1
Fork 0
mirror of https://github.com/Steffo99/todocolors.git synced 2024-11-21 15:54:18 +00:00

Create task v3

This commit is contained in:
Steffo 2024-09-13 03:47:29 +02:00
parent 48582f93df
commit db35005190
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
3 changed files with 181 additions and 8 deletions

View file

@ -5,28 +5,32 @@ use crate::outcome::LoggableOutcome;
pub mod v1;
pub mod v2;
pub use v2 as latest;
pub mod v3;
pub use v3 as latest;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum VersionedBoardChange {
V1(v1::BoardChange),
V2(v2::BoardChange),
V3(v3::BoardChange),
}
impl VersionedBoardChange {
pub fn to_latest_bc(self) -> latest::BoardChange {
match self {
VersionedBoardChange::V1(bc) => bc.into(),
VersionedBoardChange::V2(bc) => bc,
Self::V1(bc) => Self::V2(v2::BoardChange::from(bc)).to_latest_bc(),
Self::V2(bc) => Self::V3(v3::BoardChange::from(bc)).to_latest_bc(),
Self::V3(bc) => bc,
}
}
pub fn to_latest(self) -> VersionedBoardChange {
Self::V2(self.to_latest_bc())
Self::V3(self.to_latest_bc())
}
pub fn new_latest(bc: latest::BoardChange) -> VersionedBoardChange {
Self::V2(bc)
Self::V3(bc)
}
pub(crate) async fn store_in_redis_stream(&self, rconn: &mut redis::aio::Connection, key: &str) -> Result<String, ()> {

View file

@ -8,6 +8,10 @@ use chrono::serde::{ts_milliseconds, ts_milliseconds_option};
use uuid::Uuid;
use super::v1;
pub use v1::TaskIcon;
pub use v1::TaskImportance;
pub use v1::TaskPriority;
/// A change to a board's contents.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
@ -35,13 +39,13 @@ pub struct Task {
pub text: String,
#[serde(default)]
pub icon: v1::TaskIcon,
pub icon: TaskIcon,
#[serde(default)]
pub importance: v1::TaskImportance,
pub importance: TaskImportance,
#[serde(default)]
pub priority: v1::TaskPriority,
pub priority: TaskPriority,
/// When the task was created.
#[serde(default, with = "ts_milliseconds")]

165
todored/src/task/v3.rs Normal file
View file

@ -0,0 +1,165 @@
use std::collections::{HashMap, HashSet};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use chrono::serde::{ts_milliseconds, ts_milliseconds_option};
use uuid::Uuid;
use super::v2;
pub use v2::TaskImportance;
pub use v2::TaskPriority;
/// A change to a board's contents.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum BoardChange {
/// Set the board's title.
Title(String),
/// Create, update, or delete the [`Task`] with the given [`Uuid`].
Task(Uuid, Option<Task>),
/// Add the given client to the connected clients list.
Connect(Uuid),
/// Remove the given client from the connected clients list.
Disconnect(Uuid),
/// Disable editing the board.
///
/// This is only a client-side change; it is not enforced on the server side!
Lock(bool),
/// Unilaterally set the [`BoardState`], overriding everything else sent so far.
State(BoardState),
}
/// A task that can be displayed on the board.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Task {
#[serde(default)]
pub text: String,
#[serde(default)]
pub icon: String,
#[serde(default)]
pub importance: TaskImportance,
#[serde(default, with = "ts_milliseconds_option")]
pub deadline: Option<DateTime<Utc>>,
/// When the task was created.
#[serde(default, with = "ts_milliseconds")]
pub created_on: DateTime<Utc>,
/// When the task was started. If [`None`], the task hasn't been started yet.
#[serde(default, with = "ts_milliseconds_option")]
pub started_on: Option<DateTime<Utc>>,
/// When the task was completed. If [`None`], the task hasn't been completed yet.
#[serde(default, with = "ts_milliseconds_option")]
pub completed_on: Option<DateTime<Utc>>,
/// When the task was journaled. If [`None`], the task hasn't been journaled yet.
#[serde(default, with = "ts_milliseconds_option")]
pub journaled_on: Option<DateTime<Utc>>,
}
impl From<v2::BoardChange> for BoardChange {
fn from(value: v2::BoardChange) -> Self {
match value {
v2::BoardChange::Title(title) => BoardChange::Title(title),
v2::BoardChange::Task(id, opt) => BoardChange::Task(id, opt.map(|task| task.into())),
v2::BoardChange::Connect(id) => BoardChange::Connect(id),
v2::BoardChange::Disconnect(id) => BoardChange::Disconnect(id),
v2::BoardChange::Lock(value) => BoardChange::Lock(value),
v2::BoardChange::State(state) => {
let tasks: HashMap<Uuid, Task> = state.tasks.into_iter().map(|(u, t)| (u, t.into())).collect();
let state = BoardState {
title: state.title,
clients: state.clients,
locked: state.locked,
tasks,
};
BoardChange::State(state)
}
}
}
}
impl From<v2::Task> for Task {
fn from(value: v2::Task) -> Self {
Self {
text: value.text,
icon: match value.icon {
v2::TaskIcon::User => "user",
v2::TaskIcon::Image => "image",
v2::TaskIcon::Envelope => "envelope",
v2::TaskIcon::Star => "star",
v2::TaskIcon::Heart => "heart",
v2::TaskIcon::Comment => "comment",
v2::TaskIcon::FaceSmile => "face-smile",
v2::TaskIcon::File => "file",
v2::TaskIcon::Bell => "bell",
v2::TaskIcon::Bookmark => "bookmark",
v2::TaskIcon::Eye => "eye",
v2::TaskIcon::Hand => "hand",
v2::TaskIcon::PaperPlane => "paper-plane",
v2::TaskIcon::Handshake => "handshake",
v2::TaskIcon::Sun => "sun",
v2::TaskIcon::Clock => "clock",
v2::TaskIcon::Circle => "circle",
v2::TaskIcon::Square => "square",
v2::TaskIcon::Building => "building",
v2::TaskIcon::Flag => "flag",
v2::TaskIcon::Moon => "moon",
}.to_string(),
importance: value.importance,
deadline: None,
created_on: value.created_on,
started_on: value.started_on,
completed_on: value.completed_on,
journaled_on: value.journaled_on,
}
}
}
/// The complete state of a board.
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct BoardState {
/// The title of the board.
pub title: String,
/// The clients connected to the board.
pub clients: HashSet<Uuid>,
/// The tasks contained in the board.
pub tasks: HashMap<Uuid, Task>,
/// If the board is locked or not.
pub locked: bool,
}
impl BoardState {
/// Apply a [`BoardChange`] to the [`BoardState`], merging the two.
pub fn apply(&mut self, change: BoardChange) {
match change {
BoardChange::Title(title) => {
self.title = title;
}
BoardChange::Task(uuid, Some(task)) => {
self.tasks.insert(uuid, task);
}
BoardChange::Task(uuid, None) => {
self.tasks.remove(&uuid);
}
BoardChange::Connect(uuid) => {
self.clients.insert(uuid);
}
BoardChange::Disconnect(uuid) => {
self.clients.remove(&uuid);
}
BoardChange::Lock(lock) => {
self.locked = lock;
}
BoardChange::State(state) => {
self.title = state.title;
self.clients = state.clients;
self.tasks = state.tasks;
}
}
}
}