code: correcting code to display item list for a registered model

This commit is contained in:
Gabor Körber 2024-01-05 17:56:54 +01:00
parent 94845ecb0e
commit b5f9be7e5a
6 changed files with 56 additions and 16 deletions

View File

@ -134,4 +134,4 @@ As I started by quickly using a django admin template with CSS to jump start the
- implement views for app - implement views for app
- implement a static implementation for repository - implement a static implementation for repository
- eventually AdminRegistry needs to become an `Arc<Mutex<T>>`, if internal data needs to change *after* creating the main state.

View File

@ -10,13 +10,10 @@ pub mod views;
pub fn routes() -> Router<AppState> { pub fn routes() -> Router<AppState> {
Router::new() Router::new()
.route("/", get(views::index).post(views::index_action)) .route("/", get(views::index).post(views::index_action))
.route("/app/:app_key", get(views::list_app)) .route("/app/:app", get(views::list_app))
.route("/app/:app/model/:model", get(views::list_item_collection))
.route( .route(
"/app/:app_key/models/:model_key", "/app/:app/model/:model/detail/:id",
get(views::list_item_collection),
)
.route(
"/app/:app_key/models/:model_key/detail/:id",
get(views::item_details), get(views::item_details),
) )
} }

View File

@ -65,8 +65,11 @@ impl AdminRegistry {
fn model_from_internal(&self, internal_model: &internal::AdminModel) -> AdminModel { fn model_from_internal(&self, internal_model: &internal::AdminModel) -> AdminModel {
AdminModel { AdminModel {
key: internal_model.model_key.clone(), key: internal_model.model_key.clone(),
name: internal_model.model_key.clone(), name: internal_model.name.clone(),
admin_url: "".to_owned(), admin_url: format!(
"{}/app/{}/model/{}",
self.base_path, internal_model.app_key, internal_model.model_key
),
view_only: false, view_only: false,
add_url: None, add_url: None,
} }
@ -111,6 +114,14 @@ impl AdminRegistry {
self.repositories.insert(model_key, Box::new(repository)); self.repositories.insert(model_key, Box::new(repository));
Ok(()) Ok(())
} }
pub fn get_repository(&self, model_key: &str) -> Result<&Box<dyn AdminRepository>, String> {
if let Some(repo) = self.repositories.get(model_key) {
return Ok(repo);
} else {
return Err("Couldn't find repository".to_owned());
}
}
} }
pub mod config { pub mod config {
@ -139,7 +150,7 @@ mod internal {
fn from(value: super::config::AdminModelConfig) -> Self { fn from(value: super::config::AdminModelConfig) -> Self {
AdminModel { AdminModel {
app_key: value.app_key, app_key: value.app_key,
model_key: value.name.clone(), model_key: slug::slugify(value.name.clone()),
name: value.name, name: value.name,
} }
} }

View File

@ -2,11 +2,13 @@ use std::sync::Arc;
use axum::extract::Path; use axum::extract::Path;
use axum::{extract::State, response::IntoResponse, Form}; use axum::{extract::State, response::IntoResponse, Form};
use log::info;
use crate::admin::domain::{AdminApp, AdminModel}; use crate::admin::domain::{AdminApp, AdminModel};
use crate::admin::state; use crate::admin::state;
use crate::service::templates; use crate::service::templates;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Question { pub struct Question {
@ -38,6 +40,8 @@ pub struct AdminContext {
pub request: AdminRequest, pub request: AdminRequest,
pub available_apps: Vec<AdminApp>, pub available_apps: Vec<AdminApp>,
pub item_list: Option<Value>,
pub item: Option<Value>,
} }
impl Default for AdminContext { impl Default for AdminContext {
@ -56,6 +60,8 @@ impl Default for AdminContext {
request: AdminRequest { request: AdminRequest {
path: "".to_owned(), path: "".to_owned(),
}, },
item_list: None,
item: None,
} }
} }
} }
@ -88,9 +94,22 @@ pub async fn list_app(
// List Items renders the entire list item page. // List Items renders the entire list item page.
pub async fn list_item_collection( pub async fn list_item_collection(
templates: State<templates::Templates>, templates: State<templates::Templates>,
registry: State<Arc<state::AdminRegistry>>,
Path((app_key, model_key)): Path<(String, String)>, Path((app_key, model_key)): Path<(String, String)>,
) -> impl IntoResponse { ) -> impl IntoResponse {
templates.render_html("admin/items/list_items.html", ()) info!("list_item_collection {} for model {}", app_key, model_key);
let context = if let Ok(repo) = registry.get_repository(&model_key) {
// we should consider using Vec<Value> instead in get_list.
AdminContext {
item_list: Some(repo.get_list()),
..Default::default()
}
} else {
AdminContext {
..Default::default()
}
};
templates.render_html("admin/items/item_list.html", context)
} }
// Items Action is a POST to an item list. By default these are actions, that work on a list of items as input. // Items Action is a POST to an item list. By default these are actions, that work on a list of items as input.
@ -116,3 +135,8 @@ pub async fn item_action(
) -> impl IntoResponse { ) -> impl IntoResponse {
"There is your answer!".to_owned() "There is your answer!".to_owned()
} }
pub async fn debug_view(Path(data): Path<String>) -> impl IntoResponse {
println!("debug: {}", data);
"Debug!".to_owned()
}

View File

@ -0,0 +1,13 @@
{% extends "admin/base.html" %}
{% block content %}
{% if item_list %}
<ul>
{% for item in item_list %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>
{% else %}
No Items found.
{% endif %}
{% endblock content %}

View File

@ -1,5 +0,0 @@
{% if item_list %}
{% for item in item_list %}
poop: {{ item}}
{% endfor %}
{% endif %}