/* This file is part of DarkFi (https://dark.fi) * * Copyright (C) 2020-2023 Dyne.org foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use std::{fmt, str::FromStr}; use darkfi::{util::time::Timestamp, Error, Result}; use crate::due_as_timestamp; pub enum State { Open, Start, Pause, Stop, } impl State { pub const fn is_start(&self) -> bool { matches!(*self, Self::Start) } pub const fn is_pause(&self) -> bool { matches!(*self, Self::Pause) } pub const fn is_stop(&self) -> bool { matches!(*self, Self::Stop) } } impl fmt::Display for State { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { State::Open => write!(f, "open"), State::Start => write!(f, "start"), State::Stop => write!(f, "stop"), State::Pause => write!(f, "pause"), } } } impl FromStr for State { type Err = Error; fn from_str(s: &str) -> std::result::Result { let result = match s.to_lowercase().as_str() { "open" => State::Open, "stop" => State::Stop, "start" => State::Start, "pause" => State::Pause, _ => return Err(Error::ParseFailed("unable to parse state")), }; Ok(result) } } #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct BaseTask { pub title: String, pub tags: Vec, pub desc: Option, pub assign: Vec, pub project: Vec, pub due: Option, pub rank: Option, } #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct TaskInfo { pub ref_id: String, pub workspace: String, pub id: u32, pub title: String, pub tags: Vec, pub desc: String, pub owner: String, pub assign: Vec, pub project: Vec, pub due: Option, pub rank: Option, pub created_at: u64, pub state: String, pub events: Vec, pub comments: Vec, } impl From for TaskInfo { fn from(value: BaseTask) -> Self { Self { ref_id: String::default(), workspace: String::default(), id: u32::default(), title: value.title, tags: value.tags, desc: String::default(), owner: String::default(), assign: value.assign, project: value.project, due: value.due, rank: value.rank, created_at: u64::default(), state: String::default(), events: vec![], comments: vec![], } } } #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct TaskEvent { pub action: String, pub author: String, pub content: String, pub timestamp: Timestamp, } impl std::fmt::Display for TaskEvent { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "action: {}, timestamp: {}", self.action, self.timestamp) } } impl Default for TaskEvent { fn default() -> Self { Self { action: State::Open.to_string(), author: "".to_string(), content: "".to_string(), timestamp: Timestamp::current_time(), } } } #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct Comment { content: String, author: String, timestamp: Timestamp, } impl std::fmt::Display for Comment { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{} author: {}, content: {} ", self.timestamp, self.author, self.content) } } pub fn task_from_cli(values: Vec) -> Result { let mut title = String::new(); let mut tags = vec![]; let mut desc = None; let mut project = vec![]; let mut assign = vec![]; let mut due = None; let mut rank = None; for val in values { let field: Vec<&str> = val.split(':').collect(); if field.len() == 1 { if field[0].starts_with('+') || field[0].starts_with('-') { tags.push(field[0].into()); continue } title.push_str(field[0]); title.push(' '); continue } if field.len() != 2 { continue } if field[0] == "project" { project = field[1].split(',').map(|s| s.into()).collect(); } if field[0] == "desc" { desc = Some(field[1].into()); } if field[0] == "assign" { assign = field[1].split(',').map(|s| s.into()).collect(); } if field[0] == "due" { due = due_as_timestamp(field[1]) } if field[0] == "rank" { rank = Some(field[1].parse::()?); } } let title = title.trim().into(); Ok(BaseTask { title, tags, desc, project, assign, due, rank }) }