From b7588163ed6e507039b3c8db3b235bbc0f0a1e99 Mon Sep 17 00:00:00 2001 From: Manuel Gugger Date: Tue, 31 May 2022 23:13:44 +0200 Subject: [PATCH] add edit routes --- actix_admin/actix_admin_macros/src/lib.rs | 41 ++++++++++++++++++++-- actix_admin/src/builder.rs | 20 +++++------ actix_admin/src/routes/delete_post.rs | 5 +-- actix_admin/src/routes/edit_get.rs | 34 ++++++++++++++++++ actix_admin/src/routes/edit_post.rs | 25 +++++++++++++ actix_admin/src/routes/mod.rs | 7 +++- actix_admin/src/view_model.rs | 5 ++- actix_admin/templates/edit.html | 12 +++++++ actix_admin/templates/list.html | 5 +-- database.db-wal | Bin 57712 -> 107152 bytes 10 files changed, 134 insertions(+), 20 deletions(-) create mode 100644 actix_admin/src/routes/edit_get.rs create mode 100644 actix_admin/src/routes/edit_post.rs create mode 100644 actix_admin/templates/edit.html diff --git a/actix_admin/actix_admin_macros/src/lib.rs b/actix_admin/actix_admin_macros/src/lib.rs index 2e0cbfc..2dd6e6a 100644 --- a/actix_admin/actix_admin_macros/src/lib.rs +++ b/actix_admin/actix_admin_macros/src/lib.rs @@ -30,6 +30,18 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea }) .collect::>(); + let fields_for_edit_model = fields + .iter() + // TODO: filter id attr based on struct attr or sea_orm primary_key attr + .filter(|(_vis, ident, _ty)| !ident.to_string().eq("id")) + .map(|(_vis, ident, ty)| { + let ident_name = ident.to_string(); + quote! { + entity.#ident = Set(model.get_value::<#ty>(#ident_name).unwrap()) + } + }) + .collect::>(); + let fields_for_from_model = fields .iter() .map(|(_vis, ident, _ty)| { @@ -96,14 +108,37 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea model } - async fn delete_entity(db: &DatabaseConnection, mut model: ActixAdminModel) -> ActixAdminModel { + async fn get_entity(db: &DatabaseConnection, id: i32) -> ActixAdminModel { // TODO: separate primary key from other keys - let entity = Entity::find_by_id(model.get_value::("id").unwrap()).one(db).await.unwrap().unwrap(); - let delete_operation = entity.delete(db).await; + let entity = Entity::find_by_id(id).one(db).await.unwrap().unwrap(); + let model = ActixAdminModel::from(entity); model } + async fn edit_entity(db: &DatabaseConnection, id: i32, mut model: ActixAdminModel) -> ActixAdminModel { + // TODO: separate primary key from other keys + let entity: Option = Entity::find_by_id(id).one(db).await.unwrap(); + let mut entity: ActiveModel = entity.unwrap().into(); + + #(#fields_for_edit_model);*; + + let entity: Model = entity.update(db).await.unwrap(); + + model + } + + async fn delete_entity(db: &DatabaseConnection, id: i32) -> bool { + // TODO: separate primary key from other keys + let entity = Entity::find_by_id(id).one(db).await.unwrap().unwrap(); + let result = entity.delete(db).await; + + match result { + Ok(_) => true, + Err(_) => false + } + } + fn get_entity_name() -> String { Entity.table_name().to_string() } diff --git a/actix_admin/src/builder.rs b/actix_admin/src/builder.rs index 43d6bf8..acedae2 100644 --- a/actix_admin/src/builder.rs +++ b/actix_admin/src/builder.rs @@ -1,16 +1,9 @@ - - - -use actix_web::{web}; +use actix_web::web; use std::collections::HashMap; use crate::prelude::*; -use crate::routes::list; -use crate::routes::create_get; -use crate::routes::create_post; -use crate::routes::delete_post; -use crate::routes::index; +use crate::routes::{create_get, create_post, delete_post, edit_get, edit_post, index, list}; pub struct ActixAdminBuilder { pub scopes: Vec, @@ -19,7 +12,10 @@ pub struct ActixAdminBuilder { pub trait ActixAdminBuilderTrait { fn new() -> Self; - fn add_entity(&mut self, view_model: &ActixAdminViewModel); + fn add_entity( + &mut self, + view_model: &ActixAdminViewModel, + ); fn get_scope(self) -> actix_web::Scope; fn get_actix_admin(&self) -> ActixAdmin; } @@ -44,6 +40,8 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder { .route("/list", web::get().to(list::)) .route("/create", web::get().to(create_get::)) .route("/create", web::post().to(create_post::)) + .route("/edit/{id}", web::get().to(edit_get::)) + .route("/edit/{id}", web::post().to(edit_post::)) .route("/delete/{id}", web::post().to(delete_post::)), ); @@ -64,4 +62,4 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder { fn get_actix_admin(&self) -> ActixAdmin { self.actix_admin.clone() } -} \ No newline at end of file +} diff --git a/actix_admin/src/routes/delete_post.rs b/actix_admin/src/routes/delete_post.rs index 29b8c94..4fb2305 100644 --- a/actix_admin/src/routes/delete_post.rs +++ b/actix_admin/src/routes/delete_post.rs @@ -7,13 +7,14 @@ pub async fn delete_post _req: HttpRequest, data: web::Data, text: String, + id: web::Path ) -> Result { let db = &data.get_db(); let entity_name = E::get_entity_name(); let actix_admin = data.get_actix_admin(); let view_model = actix_admin.view_models.get(&entity_name).unwrap(); - let mut admin_model = ActixAdminModel::from(text); - admin_model = E::delete_entity(db, admin_model).await; + // TODO:handle any errors + let _result = E::delete_entity(db, id.into_inner()).await; Ok(HttpResponse::Found() .append_header(( diff --git a/actix_admin/src/routes/edit_get.rs b/actix_admin/src/routes/edit_get.rs new file mode 100644 index 0000000..eae193e --- /dev/null +++ b/actix_admin/src/routes/edit_get.rs @@ -0,0 +1,34 @@ +use actix_web::{error, web, Error, HttpRequest, HttpResponse}; +use tera::{Context}; + +use crate::prelude::*; + +use crate::TERA; + +pub async fn edit_get( + _req: HttpRequest, + data: web::Data, + _body: web::Payload, + text: String, + id: web::Path +) -> Result { + let db = &data.get_db(); + let entity_name = E::get_entity_name(); + let entity_names = &data.get_actix_admin().entity_names; + + let actix_admin = data.get_actix_admin(); + + let view_model = actix_admin.view_models.get(&entity_name).unwrap(); + + let model = E::get_entity(db, id.into_inner()).await; + + let mut ctx = Context::new(); + ctx.insert("entity_names", &entity_names); + ctx.insert("view_model", &view_model); + ctx.insert("model", &model); + + let body = TERA + .render("edit.html", &ctx) + .map_err(|err| error::ErrorInternalServerError(err))?; + Ok(HttpResponse::Ok().content_type("text/html").body(body)) +} \ No newline at end of file diff --git a/actix_admin/src/routes/edit_post.rs b/actix_admin/src/routes/edit_post.rs new file mode 100644 index 0000000..25f4c33 --- /dev/null +++ b/actix_admin/src/routes/edit_post.rs @@ -0,0 +1,25 @@ +use actix_web::http::header; +use actix_web::{web, Error, HttpRequest, HttpResponse}; + +use crate::prelude::*; + +pub async fn edit_post( + _req: HttpRequest, + data: web::Data, + text: String, + id: web::Path +) -> Result { + let db = &data.get_db(); + let entity_name = E::get_entity_name(); + let actix_admin = data.get_actix_admin(); + let view_model = actix_admin.view_models.get(&entity_name).unwrap(); + let mut admin_model = ActixAdminModel::from(text); + admin_model = E::edit_entity(db, id.into_inner(), admin_model).await; + + Ok(HttpResponse::Found() + .append_header(( + header::LOCATION, + format!("/admin/{}/list", view_model.entity_name), + )) + .finish()) +} \ No newline at end of file diff --git a/actix_admin/src/routes/mod.rs b/actix_admin/src/routes/mod.rs index 8f339a4..fcdfd73 100644 --- a/actix_admin/src/routes/mod.rs +++ b/actix_admin/src/routes/mod.rs @@ -10,4 +10,9 @@ mod list; pub use list::list; mod delete_post; -pub use delete_post::delete_post; \ No newline at end of file +pub use delete_post::delete_post; + +mod edit_get; +mod edit_post; +pub use edit_get::edit_get; +pub use edit_post::edit_post; \ No newline at end of file diff --git a/actix_admin/src/view_model.rs b/actix_admin/src/view_model.rs index 34ec861..fa9d4bd 100644 --- a/actix_admin/src/view_model.rs +++ b/actix_admin/src/view_model.rs @@ -13,8 +13,11 @@ pub trait ActixAdminViewModelTrait { entities_per_page: usize, ) -> Vec; + // TODO: Replace return value with proper Result Type containing Ok or Err async fn create_entity(db: &DatabaseConnection, model: ActixAdminModel) -> ActixAdminModel; - async fn delete_entity(db: &DatabaseConnection, model: ActixAdminModel) -> ActixAdminModel; + async fn delete_entity(db: &DatabaseConnection, id: i32) -> bool; + async fn get_entity(db: &DatabaseConnection, id: i32) -> ActixAdminModel; + async fn edit_entity(db: &DatabaseConnection, id: i32, model: ActixAdminModel) -> ActixAdminModel; fn get_entity_name() -> String; } diff --git a/actix_admin/templates/edit.html b/actix_admin/templates/edit.html new file mode 100644 index 0000000..f5ace6e --- /dev/null +++ b/actix_admin/templates/edit.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block content %} +
+
+ {% for key, value in model.values -%} + + {%- endfor %} + +
+
+{% endblock content %} \ No newline at end of file diff --git a/actix_admin/templates/list.html b/actix_admin/templates/list.html index e612947..1900ece 100644 --- a/actix_admin/templates/list.html +++ b/actix_admin/templates/list.html @@ -7,6 +7,7 @@ {% for model_field in view_model.fields -%} {{ model_field[0] }} {%- endfor %} + {% for entity in entities -%} @@ -14,10 +15,10 @@ {% for model_field in view_model.fields -%} {{ entity.values | get(key=model_field[0]) }} {%- endfor %} + Edit
- - +
diff --git a/database.db-wal b/database.db-wal index 77249ef4acb560ac094b7c58d114d246ea44fd4e..587a76c7dc6a5c0d1cc78e38066b2f74575b9260 100644 GIT binary patch delta 752 zcmexxhaS0PQ6SFj9a(-@ZYF-J*UQSMsFpvS_z)iYi?ONt}H~1dN5exzhFh`h* z0l7jLjzDpLy`uNh%=c?oLfrp_f&UBC{Sd8O%q$GT!a!db8kqn^P~0!lP|E6)eCQ1x z_cIgceld2H6|0V?nxi=a=6)ncm;xPv;`QBM<)0r&pVmfLs~Ni1e3e5h>?6LOg=l@v z!2cTP^@sfC!azT(Li}uKWNc&zL`E2zrCm;Si+|d=9Hbc>4c{kyF9PB zFK%aUZWfsMj^7NVo`(gPR78!9j7@+DGnk{MRedhKSAr*)S%?c}&GILwBLpiZLp=PM Xf&Vku%|akIFmMAMAuI~?FbDwv^kUkw delta 9 QcmbPml