add edit routes
This commit is contained in:
parent
7748878c26
commit
b7588163ed
@ -30,6 +30,18 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
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::<Vec<_>>();
|
||||||
|
|
||||||
let fields_for_from_model = fields
|
let fields_for_from_model = fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_vis, ident, _ty)| {
|
.map(|(_vis, ident, _ty)| {
|
||||||
@ -96,14 +108,37 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
model
|
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
|
// TODO: separate primary key from other keys
|
||||||
let entity = Entity::find_by_id(model.get_value::<i32>("id").unwrap()).one(db).await.unwrap().unwrap();
|
let entity = Entity::find_by_id(id).one(db).await.unwrap().unwrap();
|
||||||
let delete_operation = entity.delete(db).await;
|
let model = ActixAdminModel::from(entity);
|
||||||
|
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn edit_entity(db: &DatabaseConnection, id: i32, mut model: ActixAdminModel) -> ActixAdminModel {
|
||||||
|
// TODO: separate primary key from other keys
|
||||||
|
let entity: Option<Model> = 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 {
|
fn get_entity_name() -> String {
|
||||||
Entity.table_name().to_string()
|
Entity.table_name().to_string()
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
|
use actix_web::web;
|
||||||
|
|
||||||
|
|
||||||
use actix_web::{web};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::routes::list;
|
use crate::routes::{create_get, create_post, delete_post, edit_get, edit_post, index, list};
|
||||||
use crate::routes::create_get;
|
|
||||||
use crate::routes::create_post;
|
|
||||||
use crate::routes::delete_post;
|
|
||||||
use crate::routes::index;
|
|
||||||
|
|
||||||
pub struct ActixAdminBuilder {
|
pub struct ActixAdminBuilder {
|
||||||
pub scopes: Vec<actix_web::Scope>,
|
pub scopes: Vec<actix_web::Scope>,
|
||||||
@ -19,7 +12,10 @@ pub struct ActixAdminBuilder {
|
|||||||
|
|
||||||
pub trait ActixAdminBuilderTrait {
|
pub trait ActixAdminBuilderTrait {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn add_entity<T: ActixAdminAppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(&mut self, view_model: &ActixAdminViewModel);
|
fn add_entity<T: ActixAdminAppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(
|
||||||
|
&mut self,
|
||||||
|
view_model: &ActixAdminViewModel,
|
||||||
|
);
|
||||||
fn get_scope<T: ActixAdminAppDataTrait + 'static>(self) -> actix_web::Scope;
|
fn get_scope<T: ActixAdminAppDataTrait + 'static>(self) -> actix_web::Scope;
|
||||||
fn get_actix_admin(&self) -> ActixAdmin;
|
fn get_actix_admin(&self) -> ActixAdmin;
|
||||||
}
|
}
|
||||||
@ -44,6 +40,8 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
|
|||||||
.route("/list", web::get().to(list::<T, E>))
|
.route("/list", web::get().to(list::<T, E>))
|
||||||
.route("/create", web::get().to(create_get::<T, E>))
|
.route("/create", web::get().to(create_get::<T, E>))
|
||||||
.route("/create", web::post().to(create_post::<T, E>))
|
.route("/create", web::post().to(create_post::<T, E>))
|
||||||
|
.route("/edit/{id}", web::get().to(edit_get::<T, E>))
|
||||||
|
.route("/edit/{id}", web::post().to(edit_post::<T, E>))
|
||||||
.route("/delete/{id}", web::post().to(delete_post::<T, E>)),
|
.route("/delete/{id}", web::post().to(delete_post::<T, E>)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@ pub async fn delete_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
text: String,
|
text: String,
|
||||||
|
id: web::Path<i32>
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let entity_name = E::get_entity_name();
|
let entity_name = E::get_entity_name();
|
||||||
let actix_admin = data.get_actix_admin();
|
let actix_admin = data.get_actix_admin();
|
||||||
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
||||||
let mut admin_model = ActixAdminModel::from(text);
|
// TODO:handle any errors
|
||||||
admin_model = E::delete_entity(db, admin_model).await;
|
let _result = E::delete_entity(db, id.into_inner()).await;
|
||||||
|
|
||||||
Ok(HttpResponse::Found()
|
Ok(HttpResponse::Found()
|
||||||
.append_header((
|
.append_header((
|
||||||
|
34
actix_admin/src/routes/edit_get.rs
Normal file
34
actix_admin/src/routes/edit_get.rs
Normal file
@ -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<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
|
_req: HttpRequest,
|
||||||
|
data: web::Data<T>,
|
||||||
|
_body: web::Payload,
|
||||||
|
text: String,
|
||||||
|
id: web::Path<i32>
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
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))
|
||||||
|
}
|
25
actix_admin/src/routes/edit_post.rs
Normal file
25
actix_admin/src/routes/edit_post.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use actix_web::http::header;
|
||||||
|
use actix_web::{web, Error, HttpRequest, HttpResponse};
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
|
_req: HttpRequest,
|
||||||
|
data: web::Data<T>,
|
||||||
|
text: String,
|
||||||
|
id: web::Path<i32>
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
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())
|
||||||
|
}
|
@ -11,3 +11,8 @@ pub use list::list;
|
|||||||
|
|
||||||
mod delete_post;
|
mod delete_post;
|
||||||
pub use delete_post::delete_post;
|
pub use delete_post::delete_post;
|
||||||
|
|
||||||
|
mod edit_get;
|
||||||
|
mod edit_post;
|
||||||
|
pub use edit_get::edit_get;
|
||||||
|
pub use edit_post::edit_post;
|
@ -13,8 +13,11 @@ pub trait ActixAdminViewModelTrait {
|
|||||||
entities_per_page: usize,
|
entities_per_page: usize,
|
||||||
) -> Vec<ActixAdminModel>;
|
) -> Vec<ActixAdminModel>;
|
||||||
|
|
||||||
|
// TODO: Replace return value with proper Result Type containing Ok or Err
|
||||||
async fn create_entity(db: &DatabaseConnection, model: ActixAdminModel) -> ActixAdminModel;
|
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;
|
fn get_entity_name() -> String;
|
||||||
}
|
}
|
||||||
|
12
actix_admin/templates/edit.html
Normal file
12
actix_admin/templates/edit.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post">
|
||||||
|
<div class="grid">
|
||||||
|
{% for key, value in model.values -%}
|
||||||
|
<input type="text" value="{{ value }}" name="{{ key }}" placeholder="{{ key }}" aria-label="{{ key }}"><!-- required="" -->
|
||||||
|
{%- endfor %}
|
||||||
|
<button type="submit">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
@ -7,6 +7,7 @@
|
|||||||
{% for model_field in view_model.fields -%}
|
{% for model_field in view_model.fields -%}
|
||||||
<th>{{ model_field[0] }}</th>
|
<th>{{ model_field[0] }}</th>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
<th><!-- Edit Action --></th>
|
||||||
<th><!-- Delete Action --></th>
|
<th><!-- Delete Action --></th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for entity in entities -%}
|
{% for entity in entities -%}
|
||||||
@ -14,10 +15,10 @@
|
|||||||
{% for model_field in view_model.fields -%}
|
{% for model_field in view_model.fields -%}
|
||||||
<td>{{ entity.values | get(key=model_field[0]) }}</td>
|
<td>{{ entity.values | get(key=model_field[0]) }}</td>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
<td><a href="edit/{{ entity.values | get(key=view_model.fields[0][0]) }}" role="button">Edit</a></td>
|
||||||
<td>
|
<td>
|
||||||
<form method="post" action="delete/{{ entity.values | get(key=view_model.fields[0][0]) }}">
|
<form method="post" action="delete/{{ entity.values | get(key=view_model.fields[0][0]) }}">
|
||||||
<input type="hidden" id="{{ view_model.fields[0][0] }}" name="{{ view_model.fields[0][0] }}" value="{{ entity.values | get(key=view_model.fields[0][0]) }}">
|
<button type="submit">Delete</button>
|
||||||
<button type="submit" class="outline">Delete</button>
|
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
BIN
database.db-wal
BIN
database.db-wal
Binary file not shown.
Loading…
Reference in New Issue
Block a user