repo: add update data method

This commit is contained in:
Dmitriy Pleshevskiy 2022-08-05 23:40:26 +03:00
parent 8934f4ceef
commit 4dbfe41e84
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
6 changed files with 82 additions and 39 deletions

View file

@ -16,14 +16,14 @@ pub fn execute(repo: impl Repository, args: Args) {
match res { match res {
Ok(task) => { Ok(task) => {
println!("Task was added successfully"); println!("The task was added successfully");
println!(" {}", task.name); println!(" {}", task.name);
if let Some(link) = task.link { if let Some(link) = task.link {
println!(" link: {}", link); println!(" link: {}", link);
} }
} }
Err(err) => { Err(err) => {
eprintln!("Cannot insert data: {}", err); eprintln!("Cannot insert a new task: {}", err);
} }
} }

View file

@ -1,7 +1,7 @@
use std::io::Write; use std::io::Write;
use std::path::PathBuf;
use crate::{CurrentTaskInfo, Task}; use crate::repo::{self, Repository};
use crate::CurrentTaskInfo;
#[derive(clap::Args)] #[derive(clap::Args)]
pub struct Args { pub struct Args {
@ -19,33 +19,32 @@ pub struct Args {
pub struct Request { pub struct Request {
pub args: Args, pub args: Args,
pub current_task_info: Option<CurrentTaskInfo>, pub current_task_info: Option<CurrentTaskInfo>,
pub tasks: Vec<Task>,
pub tasks_file_path: PathBuf,
} }
pub fn execute(mut req: Request) { pub fn execute(repo: impl Repository, mut req: Request) {
if req.current_task_info.is_some() { if req.current_task_info.is_some() {
panic!("You can edit task only when you don't have an active task, yet"); panic!("You can edit task only when you don't have an active task, yet");
} }
let idx = req.args.idx; let args = req.args;
if idx == 0 || idx > req.tasks.len() {
panic!("invalid index");
}
let mut task = &mut req.tasks[idx - 1]; let res = repo.update_task(
if let Some(name) = req.args.name { args.idx,
task.name = name; repo::UpdateTaskData {
name: args.name,
link: args.no_link.then(|| None).or(args.link.map(Some)),
},
);
match res {
Ok(task) => {
println!("The task was changed successfully");
println!(" {}", task.name);
if let Some(link) = task.link {
println!(" link: {}", link);
}
}
Err(err) => {
eprintln!("Cannot update the task: {}", err);
} }
if let Some(link) = req.args.link {
task.link = Some(link);
} else if req.args.no_link {
task.link = None;
} }
let mut file = std::fs::File::create(&req.tasks_file_path).unwrap();
file.write_all(&serde_json::to_vec(&req.tasks).unwrap())
.unwrap();
println!("changed");
} }

View file

@ -1,3 +1,5 @@
pub type TaskId = usize;
pub struct Task { pub struct Task {
pub name: String, pub name: String,
pub link: Option<String>, pub link: Option<String>,

View file

@ -55,12 +55,13 @@ fn main() {
cli::add::execute(repo, args); cli::add::execute(repo, args);
} }
cli::SubCommand::Edit(args) => { cli::SubCommand::Edit(args) => {
cli::edit::execute(cli::edit::Request { cli::edit::execute(
repo,
cli::edit::Request {
args, args,
current_task_info, current_task_info,
tasks, },
tasks_file_path, );
});
} }
cli::SubCommand::Remove(args) => { cli::SubCommand::Remove(args) => {
cli::remove::execute(cli::remove::Request { cli::remove::execute(cli::remove::Request {

View file

@ -26,8 +26,19 @@ pub struct InsertTaskData {
link: Option<String>, link: Option<String>,
} }
pub struct UpdateTaskData {
name: Option<String>,
link: Option<Option<String>>,
}
pub trait Repository { pub trait Repository {
fn get_tasks(&self) -> Result<Vec<domain::Task>, Error>; fn get_tasks(&self) -> Result<Vec<domain::Task>, Error>;
fn update_task(
&self,
id: domain::TaskId,
update_data: UpdateTaskData,
) -> Result<domain::Task, Error>;
fn insert_task(&self, insert_data: InsertTaskData) -> Result<domain::Task, Error>; fn insert_task(&self, insert_data: InsertTaskData) -> Result<domain::Task, Error>;
} }

View file

@ -2,7 +2,7 @@ use std::fs::File;
use std::io::Write; use std::io::Write;
use crate::domain; use crate::domain;
use crate::repo::{Error, InsertTaskData, Repository}; use crate::repo::{Error, InsertTaskData, Repository, UpdateTaskData};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use xdg::BaseDirectories; use xdg::BaseDirectories;
@ -41,6 +41,32 @@ impl Repository for FsRepo {
.map(|tasks| tasks.into_iter().map(Task::into).collect()) .map(|tasks| tasks.into_iter().map(Task::into).collect())
} }
fn update_task(
&self,
id: domain::TaskId,
update_data: UpdateTaskData,
) -> Result<domain::Task, Error> {
let mut tasks = self.get_tasks_impl()?;
if id == 0 || id > tasks.len() {
return Err(Error::NotFound);
}
let mut task = &mut tasks[id];
if let Some(name) = update_data.name {
task.name = name;
}
if let Some(link) = update_data.link {
task.link = link;
}
let new_task = task.clone();
self.save_tasks_impl(tasks)?;
Ok(new_task.into())
}
fn insert_task(&self, insert_data: InsertTaskData) -> Result<domain::Task, Error> { fn insert_task(&self, insert_data: InsertTaskData) -> Result<domain::Task, Error> {
let new_task = Task { let new_task = Task {
name: insert_data.name, name: insert_data.name,
@ -50,13 +76,7 @@ impl Repository for FsRepo {
let mut tasks = self.get_tasks_impl()?; let mut tasks = self.get_tasks_impl()?;
tasks.push(new_task.clone()); tasks.push(new_task.clone());
let file_path = self self.save_tasks_impl(tasks)?;
.xdg_dirs
.place_data_file(DATA_FILE)
.map_err(|_| Error::InsertData)?;
let mut file = File::create(&file_path).map_err(|_| Error::InsertData)?;
let new_data = serde_json::to_vec(&tasks).map_err(|_| Error::InvalidData)?;
file.write_all(&new_data).map_err(|_| Error::InsertData);
Ok(new_task.into()) Ok(new_task.into())
} }
@ -69,4 +89,14 @@ impl FsRepo {
.map_err(|_| Error::NotFound) .map_err(|_| Error::NotFound)
.and_then(|file| serde_json::from_reader(file).map_err(|_| Error::InvalidData)) .and_then(|file| serde_json::from_reader(file).map_err(|_| Error::InvalidData))
} }
fn save_tasks_impl(&self, tasks: Vec<Task>) -> Result<(), Error> {
let file_path = self
.xdg_dirs
.place_data_file(DATA_FILE)
.map_err(|_| Error::InsertData)?;
let mut file = File::create(&file_path).map_err(|_| Error::InsertData)?;
let new_data = serde_json::to_vec(&tasks).map_err(|_| Error::InvalidData)?;
file.write_all(&new_data).map_err(|_| Error::InsertData)
}
} }