keep list params while in edit or show

This commit is contained in:
Manuel Gugger 2023-02-03 17:48:45 +01:00
parent 8ed3796e45
commit 683e473749
9 changed files with 262 additions and 96 deletions

View File

@ -6,11 +6,13 @@ use crate::ActixAdminNotification;
use crate::prelude::*;
use crate::TERA;
use super::DEFAULT_ENTITIES_PER_PAGE;
use super::Params;
use super::{ add_auth_context, user_can_access_page, render_unauthorized};
pub async fn create_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
_req: HttpRequest,
req: HttpRequest,
data: web::Data<T>,
_body: web::Payload,
_text: String,
@ -18,12 +20,12 @@ pub async fn create_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
let db = &data.get_db();
let model = ActixAdminModel::create_empty();
create_or_edit_get::<T, E>(&session, &data, db, Ok(model)).await
create_or_edit_get::<T, E>(&session, req, &data, db, Ok(model)).await
}
pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
_req: HttpRequest,
req: HttpRequest,
data: web::Data<T>,
_text: String,
id: web::Path<i32>
@ -31,10 +33,10 @@ pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
let db = &data.get_db();
let model = E::get_entity(db, id.into_inner()).await;
create_or_edit_get::<T, E>(&session, &data, db, model).await
create_or_edit_get::<T, E>(&session, req, &data, db, model).await
}
async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: &Session, data: &web::Data<T>, db: &sea_orm::DatabaseConnection, model_result: Result<ActixAdminModel, ActixAdminError>) -> Result<HttpResponse, Error>{
async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: &Session, req: HttpRequest, data: &web::Data<T>, db: &sea_orm::DatabaseConnection, model_result: Result<ActixAdminModel, ActixAdminError>) -> Result<HttpResponse, Error>{
let actix_admin = &data.get_actix_admin();
let mut ctx = Context::new();
add_auth_context(&session, actix_admin, &mut ctx);
@ -68,11 +70,28 @@ async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTra
.map(|err| ActixAdminNotification::from(err))
.collect();
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
let page = params.page.unwrap_or(1);
let entities_per_page = params
.entities_per_page
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
let render_partial = params.render_partial.unwrap_or(false);
let search = params.search.clone().unwrap_or(String::new());
let sort_by = params.sort_by.clone().unwrap_or(view_model.primary_key.to_string());
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
ctx.insert("select_lists", &E::get_select_lists(db).await?);
ctx.insert("base_path", &E::get_base_path(&entity_name));
ctx.insert("model", &model);
ctx.insert("notifications", &notifications);
ctx.insert("entities_per_page", &entities_per_page);
ctx.insert("render_partial", &render_partial);
ctx.insert("search", &search);
ctx.insert("sort_by", &sort_by);
ctx.insert("sort_order", &sort_order);
ctx.insert("page", &page);
let body = TERA
.render("create_or_edit.html", &ctx)

View File

@ -1,4 +1,5 @@
use super::{render_unauthorized, user_can_access_page};
use super::{Params, DEFAULT_ENTITIES_PER_PAGE};
use crate::prelude::*;
use crate::ActixAdminError;
use crate::ActixAdminNotification;
@ -7,26 +8,32 @@ use actix_multipart::Multipart;
use actix_multipart::MultipartError;
use actix_session::Session;
use actix_web::http::header;
use actix_web::{error, web, Error, HttpResponse};
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
use std::collections::HashMap;
use tera::Context;
pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,
data: web::Data<T>,
payload: Multipart,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let model = ActixAdminModel::create_from_payload(
payload,
&format!("{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name())
&format!(
"{}/{}",
actix_admin.configuration.file_upload_directory,
E::get_entity_name()
),
)
.await;
create_or_edit_post::<T, E>(&session, &data, model, None, actix_admin).await
create_or_edit_post::<T, E>(&session, req, &data, model, None, actix_admin).await
}
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,
data: web::Data<T>,
payload: Multipart,
id: web::Path<i32>,
@ -34,14 +41,27 @@ pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
let actix_admin = data.get_actix_admin();
let model = ActixAdminModel::create_from_payload(
payload,
&format!("{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name()),
&format!(
"{}/{}",
actix_admin.configuration.file_upload_directory,
E::get_entity_name()
),
)
.await;
create_or_edit_post::<T, E>(&session, &data, model, Some(id.into_inner()), actix_admin).await
create_or_edit_post::<T, E>(
&session,
req,
&data,
model,
Some(id.into_inner()),
actix_admin,
)
.await
}
pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: &Session,
req: HttpRequest,
data: &web::Data<T>,
model_res: Result<ActixAdminModel, MultipartError>,
id: Option<i32>,
@ -64,7 +84,16 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
if model.has_errors() {
errors.push(ActixAdminError::ValidationErrors);
render_form::<E>(actix_admin, view_model, db, entity_name, &model, errors).await
render_form::<E>(
req,
actix_admin,
view_model,
db,
entity_name,
&model,
errors,
)
.await
} else {
let res = match id {
Some(id) => E::edit_entity(db, id, model.clone()).await,
@ -72,21 +101,47 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
};
match res {
Ok(_) => Ok(HttpResponse::SeeOther()
Ok(_) => {
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
let page = params.page.unwrap_or(1);
let entities_per_page = params
.entities_per_page
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
let _render_partial = params.render_partial.unwrap_or(false);
let search = params.search.clone().unwrap_or(String::new());
let sort_by = params
.sort_by
.clone()
.unwrap_or(view_model.primary_key.to_string());
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
Ok(HttpResponse::SeeOther()
.append_header((
header::LOCATION,
format!("/admin/{}/list", view_model.entity_name),
format!("/admin/{0}/list?page={1}&search={2}&sort_by={3}&sort_order={4}&entities_per_page={5}", view_model.entity_name, page, search, sort_by, sort_order, entities_per_page),
))
.finish()),
.finish())
}
Err(e) => {
errors.push(e);
render_form::<E>(actix_admin, view_model, db, entity_name, &model, errors).await
render_form::<E>(
req,
actix_admin,
view_model,
db,
entity_name,
&model,
errors,
)
.await
}
}
}
}
async fn render_form<E: ActixAdminViewModelTrait>(
req: HttpRequest,
actix_admin: &ActixAdmin,
view_model: &ActixAdminViewModel,
db: &&sea_orm::DatabaseConnection,
@ -95,6 +150,28 @@ async fn render_form<E: ActixAdminViewModelTrait>(
errors: Vec<ActixAdminError>,
) -> Result<HttpResponse, Error> {
let mut ctx = Context::new();
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
let page = params.page.unwrap_or(1);
let entities_per_page = params
.entities_per_page
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
let render_partial = params.render_partial.unwrap_or(false);
let search = params.search.clone().unwrap_or(String::new());
let sort_by = params
.sort_by
.clone()
.unwrap_or(view_model.primary_key.to_string());
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
ctx.insert("entities_per_page", &entities_per_page);
ctx.insert("render_partial", &render_partial);
ctx.insert("search", &search);
ctx.insert("sort_by", &sort_by);
ctx.insert("sort_order", &sort_order);
ctx.insert("page", &page);
ctx.insert("entity_names", &actix_admin.entity_names);
ctx.insert(
"view_model",

View File

@ -1,3 +1,5 @@
use std::fmt;
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
use serde::Serialize;
use serde::{Deserialize};
@ -10,19 +12,7 @@ use crate::ActixAdminModel;
use crate::ActixAdminNotification;
use crate::TERA;
use actix_session::{Session};
use super::{ add_auth_context, user_can_access_page, render_unauthorized};
const DEFAULT_ENTITIES_PER_PAGE: u64 = 10;
#[derive(Debug, Deserialize)]
pub struct Params {
page: Option<u64>,
entities_per_page: Option<u64>,
render_partial: Option<bool>,
search: Option<String>,
sort_by: Option<String>,
sort_order: Option<SortOrder>
}
use super::{ add_auth_context, user_can_access_page, render_unauthorized, Params, DEFAULT_ENTITIES_PER_PAGE};
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum SortOrder {
@ -30,6 +20,15 @@ pub enum SortOrder {
Desc,
}
impl fmt::Display for SortOrder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SortOrder::Asc => write!(f, "Asc"),
SortOrder::Desc => write!(f, "Desc"),
}
}
}
pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,

View File

@ -20,4 +20,17 @@ mod helpers;
pub use helpers::{ add_auth_context, user_can_access_page, render_unauthorized };
mod file;
pub use file::{download, delete_file};
pub use file::{download, delete_file};
use serde::{Deserialize};
#[derive(Debug, Deserialize)]
pub struct Params {
page: Option<u64>,
entities_per_page: Option<u64>,
render_partial: Option<bool>,
search: Option<String>,
sort_by: Option<String>,
sort_order: Option<SortOrder>
}
const DEFAULT_ENTITIES_PER_PAGE: u64 = 10;

View File

@ -1,3 +1,4 @@
use actix_web::HttpRequest;
use actix_web::{error, web, Error, HttpResponse};
use actix_session::{Session};
use tera::{Context};
@ -6,9 +7,10 @@ use crate::ActixAdminNotification;
use crate::prelude::*;
use crate::TERA;
use super::{Params, DEFAULT_ENTITIES_PER_PAGE};
use super::{ add_auth_context, user_can_access_page, render_unauthorized};
pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: Session, data: web::Data<T>, id: web::Path<i32>) -> Result<HttpResponse, Error> {
pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: Session, req: HttpRequest, data: web::Data<T>, id: web::Path<i32>) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let db = &data.get_db();
@ -40,11 +42,28 @@ pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(sessio
.map(|err| ActixAdminNotification::from(err))
.collect();
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
let page = params.page.unwrap_or(1);
let entities_per_page = params
.entities_per_page
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
let render_partial = params.render_partial.unwrap_or(false);
let search = params.search.clone().unwrap_or(String::new());
let sort_by = params.sort_by.clone().unwrap_or(view_model.primary_key.to_string());
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
ctx.insert("model", &model);
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
ctx.insert("base_path", &E::get_base_path(&entity_name));
ctx.insert("entity_names", &actix_admin.entity_names);
ctx.insert("notifications", &notifications);
ctx.insert("entities_per_page", &entities_per_page);
ctx.insert("render_partial", &render_partial);
ctx.insert("search", &search);
ctx.insert("sort_by", &sort_by);
ctx.insert("sort_order", &sort_order);
ctx.insert("page", &page);
add_auth_context(&session, actix_admin, &mut ctx);

View File

@ -2,6 +2,11 @@
{% block content %}
<form hx-boost="true" hx-indicator="#loading" hx-push-url="true" hx-encoding="multipart/form-data" method="post" enctype="multipart/form-data">
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
<input type="hidden" name="search" value="{{ search }}">
<input type="hidden" name="page" value="{{ page }}">
{% for model_field in view_model.fields -%}
<div class="field">
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
@ -29,7 +34,17 @@
<button class="button is-link" type="submit">Save</i></button>
</div>
<div class="control">
<a class="button is-link is-light" href="{{ base_path }}/list">Cancel</a>
<a hx-vals='{
"entities_per_page" : "{{ entities_per_page }}",
"search" : "{{ search }}",
"sort_by" : "{{ sort_by }}",
"sort_order" : "{{ sort_order }}",
"render_partial" : "false",
"page" : "{{ page }}"
}' hx-boost="true" hx-push-url="true" hx-indicator="#loading"
class="button is-link is-light" href="{{ base_path }}/list">
Cancel
</a>
</div>
</div>
</form>

View File

@ -66,14 +66,14 @@
<div class="is-relative">
{% include "loader.html" %}
<form id="table_form" hx-indicator="#loading" hx-get="/admin/{{ entity_name }}/list"
hx-vals='{ "render_partial" : "true" }' hx-target="#{{ entity_name }}table">
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
<input type="hidden" name="search" value="{{ search }}">
<input type="hidden" name="page" value="{{ page }}">
<table class="table is-relative is-fullwidth is-hoverable is-striped">
<thead>
hx-vals='{ "render_partial" : "true" }' hx-target="#{{ entity_name }}table">
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
<input type="hidden" name="search" value="{{ search }}">
<input type="hidden" name="page" value="{{ page }}">
<table class="table is-relative is-fullwidth is-hoverable is-striped">
<thead>
<tr>
<th>
<input type="checkbox" onclick="checkAll(this)">
@ -88,7 +88,8 @@
{% endif %}
{% endif %}
</th>
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) | sort(attribute="list_sort_position") -%}
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
sort(attribute="list_sort_position") -%}
<th onclick="sort_by('{{ model_field.field_name }}');" class="is-clickable">{{
model_field.field_name | split(pat="_") | join(sep=" ") | title }}
{% if sort_by == model_field.field_name %}
@ -105,70 +106,82 @@
<!-- Delete Action -->
</th>
</tr>
</form>
</thead>
<tbody hx-indicator="#loading" hx-boost="true">
{% for entity in entities -%}
<tr>
<td><input type="checkbox" name="ids" value="{{ entity.primary_key }}"></td>
<td>
<a href="show/{{ entity.primary_key }}">
<i class="fa-solid fa-magnifying-glass"></i> {{ entity.primary_key }}
</a>
</td>
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) | sort(attribute="list_sort_position") -%}
{% if model_field.field_type == "Checkbox" %}
<td>{{ entity.values | get(key=model_field.field_name) | get_icon | safe }}</td>
{% elif model_field.field_type == "FileUpload" %}
<td><a href="file/{{ entity.primary_key }}/{{ model_field.field_name }}">{{
entity.values
| get(key=model_field.field_name) }}</a></td>
{% else %}
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
{% endif %}
{%- endfor %}
<td>
<a hx-target="body" href="edit/{{ entity.primary_key }}"><i class="fa-solid fa-pen-to-square"></i></a>
<a hx-target="closest tr" hx-confirm="Are you sure?"
hx-delete="delete/{{ entity.primary_key }}"><i class="fa-solid fa-trash"></i></a>
</td>
</tr>
{%- endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="{{ view_model.fields | length + 3 }}">
</td>
</tr>
</tfoot>
</form>
</thead>
<tbody hx-indicator="#loading" hx-boost="true">
{% for entity in entities -%}
<tr>
<td><input type="checkbox" name="ids" value="{{ entity.primary_key }}"></td>
<td>
<a href="show/{{ entity.primary_key }}" hx-vals='{
"page" : "{{ page }}",
"entities_per_page" : "{{ entities_per_page }}",
"search" : "{{ search }}",
"sort_by" : "{{ sort_by }}",
"sort_order" : "{{ sort_order }}",
"render_partial" : "true"
}' hx-target="#content">
<i class="fa-solid fa-magnifying-glass"></i> {{ entity.primary_key }}
</a>
</td>
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
sort(attribute="list_sort_position") -%}
{% if model_field.field_type == "Checkbox" %}
<td>{{ entity.values | get(key=model_field.field_name) | get_icon | safe }}</td>
{% elif model_field.field_type == "FileUpload" %}
<td><a href="file/{{ entity.primary_key }}/{{ model_field.field_name }}">{{
entity.values
| get(key=model_field.field_name) }}</a></td>
{% else %}
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
{% endif %}
{%- endfor %}
<td>
<a hx-target="body" href="edit/{{ entity.primary_key }}" hx-vals='{
"page" : "{{ page }}",
"entities_per_page" : "{{ entities_per_page }}",
"search" : "{{ search }}",
"sort_by" : "{{ sort_by }}",
"sort_order" : "{{ sort_order }}",
"render_partial" : "false"
}'>
<i class="fa-solid fa-pen-to-square"></i>
</a>
<a hx-target="closest tr" hx-confirm="Are you sure?" hx-delete="delete/{{ entity.primary_key }}">
<i class="fa-solid fa-trash"></i>
</a>
</td>
</tr>
{%- endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="{{ view_model.fields | length + 3 }}">
</td>
</tr>
</tfoot>
</table>
</form>
</form>
</div>
<nav hx-boost="true"
hx-push-url="true"
hx-target="#{{ entity_name }}table"
hx-vals='{
<nav hx-boost="true" hx-push-url="true" hx-target="#{{ entity_name }}table" hx-vals='{
"entities_per_page" : "{{ entities_per_page }}",
"search" : "{{ search }}",
"sort_by" : "{{ sort_by }}",
"sort_order" : "{{ sort_order }}",
"render_partial" : "true"
}' hx-indicator="#loading" class="pagination is-rounded is-centered" role="pagination"
aria-label="pagination">
}' hx-indicator="#loading" class="pagination is-rounded is-centered" role="pagination" aria-label="pagination">
{% if page > 1 %}
<a href="?&page={{ page - 1 }}"
class="pagination-previous left-arrow-click"><i class="fa-solid fa-arrow-left"></i>
<a href="?&page={{ page - 1 }}" class="pagination-previous left-arrow-click"><i
class="fa-solid fa-arrow-left"></i>
</a>
{% endif %}
{% if page < num_pages %} <a
href="?page={{ page + 1 }}"
class="pagination-next right-arrow-click"><i class="fa-solid fa-arrow-right"></i>
{% if page < num_pages %} <a href="?page={{ page + 1 }}" class="pagination-next right-arrow-click"><i
class="fa-solid fa-arrow-right"></i>
</a>
{% endif %}
<ul class="pagination-list">
<li>
<a class="pagination-link {% if page == 1 %}is-current{% endif %}"
href="?page={{ 1 }}"
<a class="pagination-link {% if page == 1 %}is-current{% endif %}" href="?page={{ 1 }}"
aria-label="Goto page 1">1</a>
</li>
<li>
@ -176,8 +189,7 @@
</li>
{% for i in range(start=min_show_page,end=max_show_page) %}
<li><a class="pagination-link {% if page == i+1 %}is-current{% endif %}"
aria-label="Goto page {{ i + 1 }}"
href="?page={{ i + 1 }}">{{
aria-label="Goto page {{ i + 1 }}" href="?page={{ i + 1 }}">{{
i + 1 }}</a></li>
{%- endfor %}
<li>

View File

@ -9,7 +9,8 @@
{% if model_field.field_type == "Checkbox" %}
<td>{{ model.values | get(key=model_field.field_name) | get_icon | safe }}</td>
{% elif model_field.field_type == "FileUpload" %}
<td><a href="file/{{ view_model.primary_key }}/{{ model_field.field_name }}">{{ model.values | get(key=model_field.field_name) }}</a></td>
<td><a href="file/{{ view_model.primary_key }}/{{ model_field.field_name }}">{{ model.values |
get(key=model_field.field_name) }}</a></td>
{% else %}
<td>{{ model.values | get(key=model_field.field_name) }}</td>
{% endif %}
@ -21,11 +22,18 @@
<div class="column">
<div class="field is-grouped">
<div class="control">
<a class="button is-link is-light" href="{{ base_path }}/list">Back</a>
<a hx-vals='{
"entities_per_page" : "{{ entities_per_page }}",
"search" : "{{ search }}",
"sort_by" : "{{ sort_by }}",
"sort_order" : "{{ sort_order }}",
"render_partial" : "false",
"page" : "{{ page }}"
}' hx-boost="true" hx-push-url="true" hx-indicator="#loading"
class="button is-link is-light" href="{{ base_path }}/list">Back</a>
</div>
</div>
</div>
</div>
{% endblock content %}

View File

@ -1,5 +1,6 @@
use actix_admin::prelude::*;
use actix_session::Session;
use actix_web::HttpRequest;
use actix_web::web;
use actix_web::Error;
use actix_web::HttpResponse;
@ -135,16 +136,18 @@ pub fn create_actix_admin_builder() -> ActixAdminBuilder {
async fn create_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,
data: web::Data<T>,
text: String,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let model = ActixAdminModel::from(text);
create_or_edit_post::<T, E>(&session, &data, Ok(model), None, actix_admin).await
create_or_edit_post::<T, E>(&session, req, &data, Ok(model), None, actix_admin).await
}
async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,
data: web::Data<T>,
text: String,
id: web::Path<i32>,
@ -153,6 +156,7 @@ async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewMo
let model = ActixAdminModel::from(text);
create_or_edit_post::<T, E>(
&session,
req,
&data,
Ok(model),
Some(id.into_inner()),