mirror of
https://github.com/Steffo99/todocolors.git
synced 2024-11-24 17:24: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 v1;
|
||||||
pub mod v2;
|
pub mod v2;
|
||||||
pub use v2 as latest;
|
pub mod v3;
|
||||||
|
|
||||||
|
pub use v3 as latest;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum VersionedBoardChange {
|
pub enum VersionedBoardChange {
|
||||||
V1(v1::BoardChange),
|
V1(v1::BoardChange),
|
||||||
V2(v2::BoardChange),
|
V2(v2::BoardChange),
|
||||||
|
V3(v3::BoardChange),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VersionedBoardChange {
|
impl VersionedBoardChange {
|
||||||
pub fn to_latest_bc(self) -> latest::BoardChange {
|
pub fn to_latest_bc(self) -> latest::BoardChange {
|
||||||
match self {
|
match self {
|
||||||
VersionedBoardChange::V1(bc) => bc.into(),
|
Self::V1(bc) => Self::V2(v2::BoardChange::from(bc)).to_latest_bc(),
|
||||||
VersionedBoardChange::V2(bc) => bc,
|
Self::V2(bc) => Self::V3(v3::BoardChange::from(bc)).to_latest_bc(),
|
||||||
|
Self::V3(bc) => bc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_latest(self) -> VersionedBoardChange {
|
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 {
|
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, ()> {
|
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 uuid::Uuid;
|
||||||
use super::v1;
|
use super::v1;
|
||||||
|
|
||||||
|
pub use v1::TaskIcon;
|
||||||
|
pub use v1::TaskImportance;
|
||||||
|
pub use v1::TaskPriority;
|
||||||
|
|
||||||
/// A change to a board's contents.
|
/// A change to a board's contents.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -35,13 +39,13 @@ pub struct Task {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub icon: v1::TaskIcon,
|
pub icon: TaskIcon,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub importance: v1::TaskImportance,
|
pub importance: TaskImportance,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub priority: v1::TaskPriority,
|
pub priority: TaskPriority,
|
||||||
|
|
||||||
/// When the task was created.
|
/// When the task was created.
|
||||||
#[serde(default, with = "ts_milliseconds")]
|
#[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