miniweb/src/admin_examples/static_repository.rs

183 lines
5.7 KiB
Rust

use crate::depot::prelude::*;
use async_trait::async_trait;
use log::debug;
use serde_json::{json, Value};
/// This is a showcase implementation with a static repository
/// It uses a Vec<Value> to store it's data.
struct MyStaticRepository {
/// In Memory Storage for Example.
content: Vec<Value>,
/// 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 DepotRepository for MyStaticRepository {
type Key = i64;
fn key_from_string(&self, s: String) -> Option<Self::Key> {
if let Ok(i) = s.parse::<i64>() {
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) -> RepositoryResult {
let id = *id as usize;
let item = self.content.get(id - 1).cloned().unwrap();
let id = item.get("id").unwrap();
Ok(RepositoryResponse::ItemOnly(
model.build_item(&*id.to_string(), item),
))
}
async fn list(&self, model: &RepositoryContext) -> RepositoryList {
RepositoryList::List {
values: self
.content
.clone()
.into_iter()
.filter_map(|item| match item.get("id") {
Some(id_value) => {
let id_str = id_value.to_string();
Some(model.build_item(&id_str, item))
}
None => {
eprintln!("Skipping item due to missing 'id'");
None
}
})
.collect(),
}
}
async fn create(&mut self, model: &RepositoryContext, mut data: Value) -> RepositoryResult {
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
Ok(RepositoryResponse::ItemOnly(
model.build_item(&*new_id.to_string(), data),
))
}
async fn update(
&mut self,
model: &RepositoryContext,
id: &Self::Key,
data: Value,
) -> RepositoryResult {
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();
item["id"] = (*id).into();
if let Some(item_id) = item.get("id") {
return Ok(RepositoryResponse::ItemOnly(
model.build_item(&*item_id.to_string(), data),
));
}
}
Ok(RepositoryResponse::NoItem)
}
async fn replace(
&mut self,
model: &RepositoryContext,
id: &Self::Key,
data: Value,
) -> RepositoryResult {
self.update(model, id, data).await
}
async fn delete(&mut self, _: &RepositoryContext, id: &Self::Key) -> Option<Value> {
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 DepotRegistry) {
let section_key = registry.register_section("Example App");
let repo = MyStaticRepository::new();
let model_config = DepotModelConfig {
section_key: section_key,
name: "ExampleModel".to_owned(),
};
let model_result = registry.register_model(model_config, repo);
match model_result {
Err(err) => panic!("{}", err),
_ => (),
}
}