From 94845ecb0ea6edf4b58133fc2b97075722ca4861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabor=20K=C3=B6rber?= Date: Thu, 4 Jan 2024 17:51:08 +0100 Subject: [PATCH] code: moving static example into a repository, and implementing app/model listing. --- NOTES.md | 5 +++++ src/admin/example.rs | 36 +++++++++++++++++++++++++++++++++ src/admin/mod.rs | 1 + src/admin/state.rs | 47 ++++++++++++++++++++++++++------------------ src/admin/views.rs | 37 ++-------------------------------- src/main.rs | 4 ++-- 6 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 src/admin/example.rs diff --git a/NOTES.md b/NOTES.md index 25fe84e..a3ae7bf 100644 --- a/NOTES.md +++ b/NOTES.md @@ -130,3 +130,8 @@ As I started by quickly using a django admin template with CSS to jump start the | object_name\|lower | key, app_key, model_key | | | app_label | key, app_key | | +### Next Steps: + + - implement views for app + - implement a static implementation for repository + \ No newline at end of file diff --git a/src/admin/example.rs b/src/admin/example.rs new file mode 100644 index 0000000..48b8be0 --- /dev/null +++ b/src/admin/example.rs @@ -0,0 +1,36 @@ +// implementation of static repository + +use super::state::{config::AdminModelConfig, AdminRegistry, AdminRepository}; +use serde_json::{json, Value}; + +struct MyStaticRepository {} + +impl AdminRepository for MyStaticRepository { + fn get_item(&self, id: usize) -> Option { + Some(json!({ + "name": "Adam", + "age": id, + })) + } + + fn get_list(&self) -> Value { + json!([ + {"name": "Strange", "age": 150 }, + {"name": "Adam", "age": 12} + ]) + } +} + +pub fn register_example(registry: &mut AdminRegistry) { + let app_key = registry.register_app("Example App"); + let repo = MyStaticRepository {}; + let model_config = AdminModelConfig { + app_key: app_key, + name: "ExampleModel".to_owned(), + }; + let model_result = registry.register_model(model_config, repo); + match model_result { + Err(err) => panic!("{}", err), + _ => (), + } +} diff --git a/src/admin/mod.rs b/src/admin/mod.rs index 1663260..8b51036 100644 --- a/src/admin/mod.rs +++ b/src/admin/mod.rs @@ -3,6 +3,7 @@ use axum::{routing::get, Router}; use crate::state::AppState; pub mod domain; +pub mod example; pub mod state; pub mod views; diff --git a/src/admin/state.rs b/src/admin/state.rs index 36c31f3..73a321e 100644 --- a/src/admin/state.rs +++ b/src/admin/state.rs @@ -36,32 +36,48 @@ impl AdminRegistry { .collect() } - fn get_app(&self, name: &str, node: &internal::AdminApp) -> AdminApp { + fn get_app(&self, key: &str, node: &internal::AdminApp) -> AdminApp { + let my_models = self.get_models(key); AdminApp { - name: name.to_owned(), - key: node.key.to_owned(), - app_url: name.to_owned().to_lowercase(), - models: vec![], + name: key.to_owned(), + key: node.name.to_owned(), + app_url: key.to_owned(), + models: my_models, } } - pub fn register_app(&mut self, name: &str, app_label: &str, app_url: &str) { + pub fn register_app(&mut self, name: &str) -> String { let key = self.get_key(name); self.apps.insert( key.to_owned(), internal::AdminApp { - key: key, + key: key.to_owned(), name: name.to_owned(), }, ); + key } fn get_key(&self, name: &str) -> String { slug::slugify(name) } + fn model_from_internal(&self, internal_model: &internal::AdminModel) -> AdminModel { + AdminModel { + key: internal_model.model_key.clone(), + name: internal_model.model_key.clone(), + admin_url: "".to_owned(), + view_only: false, + add_url: None, + } + } + pub fn get_models(&self, app_key: &str) -> Vec { - vec![] + self.models + .iter() + .filter(|(key, _)| key.starts_with(&format!("{}.", app_key))) + .map(|(_, model)| self.model_from_internal(model)) + .collect() } pub fn get_model(&self, app_key: &str, model_key: &str) -> Option { @@ -69,13 +85,7 @@ impl AdminRegistry { let internal_model = self.models.get(&full_model_key)?; // unfinished: we need to think about model_key vs. model_id vs. entry_id, as "name" is ambiguous. - Some(AdminModel { - key: internal_model.model_key.clone(), - name: internal_model.model_key.clone(), - admin_url: "".to_owned(), - view_only: false, - add_url: None, - }) + Some(self.model_from_internal(internal_model)) } fn register_model_config(&mut self, model: config::AdminModelConfig) -> Result { @@ -87,10 +97,9 @@ impl AdminRegistry { if self.models.contains_key(&local_config_name) { return Err(format!("Model {} already exists", local_config_name)); } - if let Some(local_config) = self.models.insert(local_config_name, local_config) { - return Ok(local_config.model_key); - } - Err("Model could not be added!".to_owned()) + let model_key = local_config.model_key.clone(); + self.models.insert(local_config_name, local_config); + Ok(model_key) } pub fn register_model( diff --git a/src/admin/views.rs b/src/admin/views.rs index 21c15d5..9e46be9 100644 --- a/src/admin/views.rs +++ b/src/admin/views.rs @@ -62,45 +62,12 @@ impl Default for AdminContext { pub async fn index( templates: State, - administration: State>, + registry: State>, ) -> impl IntoResponse { - let models = vec![ - AdminModel { - name: "User".to_owned(), - key: "user".to_owned(), - admin_url: "/admin/app/users/user".to_owned(), - view_only: false, - add_url: Some("/admin/users/user/add".to_owned()), - }, - AdminModel { - name: "Group".to_owned(), - key: "group".to_owned(), - admin_url: "/admin/users/group".to_owned(), - view_only: false, - add_url: None, - }, - AdminModel { - name: "Permission".to_owned(), - key: "permission".to_owned(), - admin_url: "/admin/users/permission".to_owned(), - view_only: true, - add_url: None, - }, - ]; - let core_app = AdminApp { - name: "Admin".to_owned(), - key: "admin".to_owned(), - app_url: "/admin/users/".to_owned(), - models: models, - }; - - let mut available = vec![core_app]; - available.extend(administration.get_apps()); - templates.render_html( "admin/index.html", AdminContext { - available_apps: available, + available_apps: registry.get_apps(), ..Default::default() }, ) diff --git a/src/main.rs b/src/main.rs index 317f6f0..be5db81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod howto; mod service; mod state; +use crate::admin::example; use crate::service::{handlers, templates}; use crate::state::AppState; use axum::{ @@ -32,8 +33,7 @@ async fn main() { // Prepare App State let tmpl = templates::Templates::initialize().expect("Template Engine could not be loaded."); let mut admin = admin::state::AdminRegistry::new("admin"); - admin.register_app("auth", "Authorities", "auth"); - //let admin_router = admin.generate_router(); + example::register_example(&mut admin); let state: AppState = AppState { templates: tmpl,