183 lines
5.7 KiB
Rust
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),
|
|
_ => (),
|
|
}
|
|
}
|