diff --git a/src/main.rs b/src/main.rs index b590417bcd17d67efaf3b175bb0c511a65d18bf3..66b5818fc0ce8fddcf3f7d896547cde3fc62bd90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,7 +66,8 @@ async fn main() -> std::io::Result<()> { .service(service::files::delete_static_file) .service(service::add_template) .service(service::update_template) - .service(service::remove_page), + .service(service::remove_page) + .service(service::remove_template), ), ) .service(service::files::favicon) diff --git a/src/service/website.rs b/src/service/website.rs index 186761ca3662be3dad078090974a16be9037c9ed..139cf98e9976efccb059c423a61d5109fa16d36c 100644 --- a/src/service/website.rs +++ b/src/service/website.rs @@ -170,6 +170,7 @@ pub async fn remove_page( let mut website = website .write() .expect("Couldn't acquire website write lock"); + match website.remove_page(id.into_inner()) { Ok(()) => { website @@ -180,3 +181,27 @@ pub async fn remove_page( Err(msg) => HttpResponse::BadRequest().body(msg), } } + +#[delete("remove-template/{name}")] +pub async fn remove_template( + name: actix_web::web::Path<String>, + app_state: Data<RwLock<AppState>>, + website: Data<RwLock<WebSite>>, +) -> HttpResponse { + let mut website = website + .write() + .expect("Couldn't acquire website write lock"); + + match website.remove_template(name.into_inner()) { + Ok(()) => { + if let Err(msg) = + website.save(&app_state.read().expect("Couldn't read AppState").config) + { + return HttpResponse::InternalServerError() + .body(format!("Error saving website to static file {}", msg)); + } + HttpResponse::Accepted().finish() + } + Err(msg) => HttpResponse::BadRequest().body(msg), + } +} diff --git a/src/website/website.rs b/src/website/website.rs index 229850ef46d5796c4ca323f5639bec72133d2fae..e5257e11f9cb8c2ac3a734c723ce583c33ad98c7 100644 --- a/src/website/website.rs +++ b/src/website/website.rs @@ -194,14 +194,7 @@ impl WebSite { page: &'a Page, parent_id: Option<usize>, match_id: usize, - ) -> Result<usize, String> { - let parent_id = { - if parent_id.is_none() { - return Err("Page must have a parent".to_string()); - } - parent_id.unwrap() - }; - + ) -> Result<Option<usize>, String> { if page.get_id() == match_id { return Ok(parent_id); } @@ -223,7 +216,7 @@ impl WebSite { Self::find_page_mut(&mut self.root_page, id) } - fn get_page_parent_id(&self, id: usize) -> Result<usize, String> { + fn get_page_parent_id(&self, id: usize) -> Result<Option<usize>, String> { Self::find_page_parent_id(&self.root_page, None, id) } @@ -295,12 +288,14 @@ impl WebSite { Ok(()) } - fn get_template(&self, name: &String) -> Option<&PageTemplate> { - self.templates.iter().find(|t| t.name.eq(name)) + fn get_template<S: Into<String>>(&self, name: S) -> Option<&PageTemplate> { + let name = name.into(); + self.templates.iter().find(|t| t.name.eq(&name)) } - fn get_template_mut(&mut self, name: &String) -> Option<&mut PageTemplate> { - self.templates.iter_mut().find(|t| t.name.eq(name)) + fn get_template_mut<S: Into<String>>(&mut self, name: S) -> Option<&mut PageTemplate> { + let name = name.into(); + self.templates.iter_mut().find(|t| t.name.eq(&name)) } pub fn add_template(&mut self, new_template: PageTemplate) -> Result<&PageTemplate, String> { @@ -329,6 +324,36 @@ impl WebSite { } } + fn validate_remove_template(&self, name: &String) -> Result<(), String> { + for p in self.get_all_pages_as_vec() { + if p.template_name.eq(name) { + return Err(format!( + "Template \"{}\" is used by page \"{}\" and can't be removed", + name, p.metadata.url_slug + )); + } + } + + Ok(()) + } + + pub fn remove_template<S: Into<String>>(&mut self, name: S) -> Result<(), String> { + let name: String = name.into(); + + if let Err(msg) = self.validate_remove_template(&name) { + return Err(msg); + } + + self.templates = self + .templates + .iter() + .filter(|t| !t.name.eq(&name)) + .map(|t| t.clone()) + .collect::<Vec<PageTemplate>>(); + + Ok(()) + } + pub fn update_page_rec_after_template_update(page: &mut Page, template: &PageTemplate) { page.update_template_if_same_name(template); for sp in page.sub_pages.iter_mut() { @@ -337,12 +362,13 @@ impl WebSite { } fn validate_page_to_remove(&mut self, id: usize) -> Result<usize, String> { - let res = self.get_page_parent_id(id); - if let Err(msg) = res { - return Err(msg); + match self.get_page_parent_id(id) { + Ok(parent_id) => match parent_id { + Some(parent_id) => Ok(parent_id), + None => Err("Page must have a parent".to_string()), + }, + Err(msg) => Err(msg), } - - Ok(res.unwrap()) } pub fn remove_page(&mut self, id: usize) -> Result<(), String> { @@ -365,7 +391,39 @@ impl WebSite { #[cfg(test)] mod test_website { use super::*; - + const TEST_TEMPLATE: &'static str = " +{ + \"name\": \"TEST TEMPLATE 2\", + \"layout\": {}, + \"contents\": [ + { + \"tag\": \"div\", + \"attrs\": { + \"class\": \"page-template\" + }, + \"contents\": [ + { + \"tag\": \"header\", + \"contents\": [ + { + \"tag\": \"nav\" + } + ] + }, + { + \"tag\": \"div\", + \"attrs\": { + \"id\": \"page-body\" + } + }, + { + \"tag\": \"footer\" + } + ] + } + ] +} + "; fn test_website(pth: &PathBuf) -> WebSite { WebSiteBuilder::testing(pth).build().unwrap() } @@ -454,50 +512,16 @@ mod test_website { #[test] fn add_template() { - let test_template: &'static str = " -{ - \"name\": \"TEST ADD TEMPLATE\", - \"layout\": {}, - \"contents\": [ - { - \"tag\": \"div\", - \"attrs\": { - \"class\": \"page-template\" - }, - \"contents\": [ - { - \"tag\": \"header\", - \"contents\": [ - { - \"tag\": \"nav\" - } - ] - }, - { - \"tag\": \"div\", - \"attrs\": { - \"id\": \"page-body\" - } - }, - { - \"tag\": \"footer\" - } - ] - } - ] -} - "; - let test_dir = PathBuf::from("./test"); let mut ws = test_website(&test_dir); - let new_template: PageTemplate = serde_json::from_str(test_template).unwrap(); + let new_template: PageTemplate = serde_json::from_str(TEST_TEMPLATE).unwrap(); let add_template_res = ws.add_template(new_template); assert!(add_template_res.is_ok()); let added_template = add_template_res.unwrap(); - assert_eq!(added_template.name, "TEST ADD TEMPLATE"); + assert_eq!(added_template.name, "TEST TEMPLATE 2"); remove_test_dir(&test_dir); } @@ -532,10 +556,25 @@ mod test_website { let test_dir = PathBuf::from("./test"); let mut ws = test_website(&test_dir); let remove_root_page = ws.remove_page(1); - assert!(remove_root_page.is_err()); + assert!(remove_root_page.is_err()); // Shouldn't be able to remove root page let remove_subpage = ws.remove_page(2); assert!(remove_subpage.is_ok()); assert!(ws.get_page(2).is_none()); remove_test_dir(&test_dir); } + + #[test] + fn test_remove_template() { + let test_dir = PathBuf::from("./test"); + let mut ws = test_website(&test_dir); + let mut res = ws.remove_template("TEST TEMPLATE"); + assert!(res.is_err()); // Template shouldn't be removable if it's used + + ws.add_template(serde_json::from_str(TEST_TEMPLATE).unwrap()) + .unwrap(); + res = ws.remove_template("TEST TEMPLATE 2"); + assert!(res.is_ok()); + assert!(ws.get_template("TEST TEMPLATE 2").is_none()); + remove_test_dir(&test_dir); + } }