use crate::admin::domain::*; use crate::admin::state::AdminRegistry; use async_trait::async_trait; use log::{debug, warn}; use serde_json::{json, Value}; /// This is a showcase implementation with a static repository /// It uses a Vec to store it's data. struct MyStaticRepository { /// In Memory Storage for Example. content: Vec, /// ID Counter for content. next_id: usize, } impl MyStaticRepository { pub fn new() -> Self { MyStaticRepository { next_id: 12, content: vec![ json!({"id": 1, "name": "Strange", "age": 150, "level": "master" }), json!({"id": 2, "name": "Adam", "age": 12, "powers": 8}), json!({"id": 3, "name": "Tony", "age": 42, "powers": 0}), json!({"id": 4, "name": "Rex", "age": 72}), json!({"id": 5, "name": "Justin", "age": 46}), json!({"id": 6, "name": "Reacher", "age": 39, "level": "adept", "powers": 0}), json!({"id": 7, "name": "Arnold", "age": 7}), json!({"id": 8, "name": "Eight", "age": 8}), json!({"id": 9, "name": "Nine", "age": 9}), json!({"id": 10, "name": "Ten", "age": 10}), json!({"id": 11, "name": "Eleven", "age": 11}), ], } } } #[async_trait] impl AdminRepository for MyStaticRepository { type Key = i64; fn key_from_string(&self, s: String) -> Option { if let Ok(i) = s.parse::() { Some(i) } else { None } } async fn info(&self, _: &RepositoryContext) -> RepositoryInfo { RepoInfo { name: "My Static Repository", lookup_key: "id", display_list: &["id", "name", "level", "age"], fields: &["name", "level", "age", "powers"], } .build() //.set_widget("age", Widget::default().as_password().labeled("hi there.")) //.set_widget("name", Widget::textarea().options(&[("disabled", "true")])) } async fn get(&self, model: &RepositoryContext, id: &Self::Key) -> Option { let id = *id as usize; let item = self.content.get(id - 1).cloned().unwrap(); let id = item.get("id").unwrap(); Some(model.build_item(&*id.to_string(), item)) } async fn list(&self, model: &RepositoryContext) -> RepositoryList { RepositoryList::List { values: self .content .clone() .into_iter() .map(|item| model.build_item(&*item.get("id").unwrap().to_string(), item)) .collect(), } } async fn create( &mut self, model: &RepositoryContext, mut data: Value, ) -> Option { debug!("Asked to create: {}", data); let new_id = self.next_id; self.next_id += 1; data["id"] = Value::Number(new_id.into()); debug!("I create: {}", data); // Push the data into the repository self.content.push(data.clone()); // Return the newly created item Some(model.build_item(&*new_id.to_string(), data)) } async fn update( &mut self, model: &RepositoryContext, id: &Self::Key, data: Value, ) -> Option { debug!("I would now update: {}, {}", id, data); // First, find the index of the item to update let item_index = self.content.iter().position(|item| { if let Some(item_id) = item.get("id") { item_id == id } else { false } }); // Then, update the item if found if let Some(index) = item_index { let item = &mut self.content[index]; *item = data.clone(); if let Some(item_id) = item.get("id") { return Some(model.build_item(&*item_id.to_string(), data)); } } None } async fn replace( &mut self, model: &RepositoryContext, id: &Self::Key, data: Value, ) -> Option { self.update(model, id, data).await } async fn delete(&mut self, _: &RepositoryContext, id: &Self::Key) -> Option { debug!("Would delete: {}", id); let item_index = self.content.iter().position(|item| { if let Some(item_id) = item.get("id") { item_id == id } else { false } }); if let Some(index) = item_index { // Remove and return the item Some(self.content.remove(index)) } else { None } } } pub fn register(registry: &mut AdminRegistry) { let app_key = registry.register_app("Example App"); let repo = MyStaticRepository::new(); 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), _ => (), } }