~jshsj/rust_todo

f88eef58a9d1867152e6352ad31cc9e789008292 — JSH 1 year, 9 months ago 7c8f9a0 master
changed vec<Task> to HashMap<String, Task>
3 files changed, 143 insertions(+), 39 deletions(-)

M src/main.rs
M src/tasks.rs
D tasks/finish_this.
M src/main.rs => src/main.rs +7 -9
@@ 1,21 1,19 @@
#[macro_use] extern crate failure;
#[macro_use]
extern crate failure;

use std::fmt;
use std::io::{Read, Write, BufReader, BufRead};
use std::io::{BufRead, BufReader, Read, Write};

use serde;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
extern crate chrono;
use chrono::{DateTime, Utc, TimeZone};
use chrono::{DateTime, TimeZone, Utc};

mod tasks;


fn main() {
    let mut task_manager = tasks::TaskManager::new();
    for task in task_manager.all_tasks() {
        println!("{}", task);
        
    for (name, task) in task_manager.all_tasks().iter() {
        println!("{}{}", name, task);
    }
}


M src/tasks.rs => src/tasks.rs +136 -29
@@ 1,38 1,38 @@
use chrono::{DateTime, Utc};
use serde;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use serde_json;
use chrono::{DateTime, Utc, TimeZone};
use std::collections::HashMap;
use std::fmt;
use std::fs::{read_dir, File};
use std::fs::{read_dir, remove_file, File};

use failure::Error;

static PATH_PREFIX: &str = "./tasks/";

#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Task {
    pub name: String,
    pub path: String,
    pub sub_tasks: Vec<SubTask>,
    pub sub_tasks: HashMap<String, SubTask>,
    pub done: bool,
    pub due_date: Option<DateTime<Utc>>,
}

#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct SubTask {
    pub name: String,
    pub done: bool,
    pub due_date: Option<DateTime<Utc>>,
}


impl Task {
    fn new(name: String, due_date: Option<DateTime<Utc>>) -> Result<Task, Error> {
        let path = convert_name_to_path(&name);
        let t = Task {
            name,
            path,
            sub_tasks: Vec::<SubTask>::new(),
            sub_tasks: HashMap::<String, SubTask>::new(),
            done: false,
            due_date,
        };


@@ 41,17 41,29 @@ impl Task {
    }

    fn add_subtask(&mut self, name: String, due_date: Option<DateTime<Utc>>) -> Result<(), Error> {
        self.sub_tasks.push(SubTask::new(name, due_date));
        self.sub_tasks
            .insert(name.clone(), SubTask::new(name, due_date));
        self.save()?;
        Ok(())
    }

    fn remove_subtask(&mut self, name: String) -> Result<(), Error> {
        match self.sub_tasks.remove(&name) {
            Some(_t) => Ok(()),
            None => bail!("Task not found"),
        }
    }

    fn save(&self) -> Result<(), Error> {
        let file = File::create(format!("{}{}", PATH_PREFIX, self.path))
            .expect("Couldn't create file");
        let file = File::create(format!("{}{}", PATH_PREFIX, self.path))?;
        serde_json::to_writer(file, &self)?;
        Ok(())
    }

    fn delete(&self) -> Result<(), Error> {
        remove_file(format!("{}{}", PATH_PREFIX, self.path))?;
        Ok(())
    }
}

impl SubTask {


@@ 77,44 89,76 @@ impl fmt::Display for SubTask {
}

pub struct TaskManager {
    tasklist: Vec<Task>
    tasklist: HashMap<String, Task>,
}

impl TaskManager {
    pub fn new() -> TaskManager {
        let mut t = TaskManager {
            tasklist: Vec::<Task>::new()
            tasklist: HashMap::<String, Task>::new(),
        };
        t.init();
        t
    }

    pub fn add_task(&mut self, name: String) -> Result<(), Error> {
        self.tasklist.push(Task::new(name, None)?);
        self.tasklist.insert(name.clone(), Task::new(name, None)?);
        Ok(())
    }

    pub fn add_task_with_date(
        &mut self,
        name: String,
        due_date: DateTime<Utc>,
    ) -> Result<(), Error> {
        self.tasklist
            .insert(name.clone(), Task::new(name, Some(due_date))?);
        Ok(())
    }

    pub fn add_subtask(&mut self, task_name: String, subtask_name: String) -> Result<(), Error> {
        let task: &mut Task = self.get_task_by_name(task_name)?;
        &task.add_subtask(subtask_name, None)?;
        Ok(())
    }

    pub fn add_task_with_date(&mut self, name: String, due_date: DateTime<Utc>) -> Result<(), Error> {
        self.tasklist.push(Task::new(name, Some(due_date))?);
    pub fn add_substask_with_date(
        &mut self,
        task_name: String,
        subtask_name: String,
        due_date: DateTime<Utc>,
    ) -> Result<(), Error> {
        let task: &mut Task = self.get_task_by_name(task_name)?;
        &task.add_subtask(subtask_name, Some(due_date))?;
        Ok(())
    }

    pub fn add_subtask_to_task(&mut self, task_name: String, subtask_name: String) -> Result<(),Error> {
        let mut task = self.get_task_by_name(task_name)?;
        task.add_subtask(subtask_name, None)?;
    pub fn remove_subtask(&mut self, task_name: String, subtask_name: String) -> Result<(), Error> {
        let task: &mut Task = self.get_task_by_name(task_name)?;
        &task.remove_subtask(subtask_name)?;
        Ok(())
    }

    fn get_task_by_name(&mut self, task_name: String) -> Result<&mut Task, Error> {
        match self.tasklist.get_mut(&task_name) {
            Some(task) => Ok(&mut *task),
            None => bail!("Task not found"),
        }
        //let tasklist: Vec<Task> = self.tasklist.as_ref();
        //let filtered: Vec<Task> = tasklist.into_iter().filter(|t| t.name == task_name).collect();
    }

    pub fn get_task_by_name(&mut self, task_name: String) -> Result<Task, Error> {
        let filtered: Vec<Task> = self.tasklist.as_ref().into_iter().filter(|t| t.name == task_name).collect();
        if filtered.is_empty() {
            bail!("No Item founds")
    pub fn delete_task(&mut self, task_name: String) -> Result<(), Error> {
        match self.tasklist.get_mut(&task_name) {
            Some(task) => {
                task.delete()?;
                Ok(())
            }
            None => bail!("Task not found"),
        }
        Ok(filtered[0])
    }

    pub fn all_tasks(&mut self) -> &Vec<Task> {
    pub fn all_tasks(&mut self) -> &HashMap<String, Task> {
        &self.tasklist
    }



@@ 129,9 173,9 @@ impl TaskManager {

    fn load_task(&mut self, path: String) {
        let file = File::open(&path).unwrap();
        let task: Task = serde_json::from_reader(file)
            .expect(format!("Can't parse file {}", path).as_str());
        self.tasklist.push(task);
        let task: Task =
            serde_json::from_reader(file).expect(format!("Can't parse file {}", path).as_str());
        self.tasklist.insert(String::from(task.name.as_str()), task);
    }
}



@@ 157,4 201,67 @@ fn read_task_files() -> Vec<String> {
    }

    task_files
}
\ No newline at end of file
}

#[cfg(test)]
mod tests {
    use super::*;

    fn setup_test_manager(test: String) -> TaskManager {
        let mut task_manager = TaskManager::new();
        task_manager.add_task(String::from(test)).unwrap();
        task_manager
    }

    fn destroy(test: String) {
        remove_file(format!("./tasks/{}", test)).unwrap();
    }

    #[test]
    fn add_task() {
        let mut task_manager = TaskManager::new();
        let task = Task::new(String::from("Test"), None).unwrap();
        assert!(task_manager.add_task(String::from("Test")).is_ok());
        assert_eq!(
            task.name,
            task_manager
                .get_task_by_name(String::from("Test"))
                .unwrap()
                .name
        );
        destroy(String::from("test"));
    }

    #[test]
    fn add_subtask() {
        let mut manager = setup_test_manager(String::from("add_subtask"));
        assert!(manager
            .add_subtask(String::from("add_subtask"), String::from("Subtask"))
            .is_ok());
        assert!(manager
            .get_task_by_name(String::from("add_subtask"))
            .unwrap()
            .sub_tasks
            .contains_key("Subtask"));

        destroy(String::from("add_subtask"));
    }

    #[test]
    #[should_panic]
    fn add_subtask_to_nonexisting_task() {
        let mut manager = setup_test_manager(String::from("add_subtask_panic"));
        manager
            .add_subtask(String::from("thats not happening"), String::from("SDADA"))
            .unwrap();
        destroy(String::from("add_subtask_panic"));
    }

    #[test]
    fn delete_task() {
        let mut manager = setup_test_manager(String::from("delete_task"));
        manager.add_task(String::from("test_delete")).unwrap();
        assert!(manager.delete_task(String::from("test_delete")).is_ok());
        destroy(String::from("delete_task"));
    }
}

D tasks/finish_this. => tasks/finish_this. +0 -1
@@ 1,1 0,0 @@
{"name":"Finish this.","path":"finish_this.","sub_tasks":[],"done":false,"due_date":"2019-02-11T10:12:44.961489753Z"}
\ No newline at end of file