mirror of
https://github.com/Steffo99/todocolors.git
synced 2024-11-21 07:44:18 +00:00
Create task v3
This commit is contained in:
parent
48582f93df
commit
db35005190
3 changed files with 181 additions and 8 deletions
|
@ -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, ()> {
|
||||
|
|
|
@ -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
165
todored/src/task/v3.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue