Skip to main content

actix_web_admin/
resource.rs

1use async_trait::async_trait;
2use std::collections::HashMap;
3use crate::types::*;
4use serde::Serialize;
5
6/// Newtype for the admin site title to avoid Data<String> collisions.
7#[derive(Clone)]
8pub struct AdminTitle(pub String);
9
10/// Newtype for the admin site prefix to avoid Data<String> collisions.
11#[derive(Clone)]
12pub struct AdminPrefix(pub String);
13
14/// Information about a resource for serialization (e.g. for Tera templates).
15#[derive(Serialize, Debug)]
16pub struct ResourceInfo {
17    pub name: String,
18    pub plural_name: String,
19    pub slug: String,
20    pub icon: String,
21    pub path_list: String,
22    pub path_new: String,
23    pub path_edit: String,
24    pub path_delete: String,
25}
26
27/// Trait to be implemented by any resource that should be managed by the admin backoffice.
28#[async_trait]
29pub trait AdminResource: Send + Sync + 'static {
30    /// Display name of the resource.
31    fn name(&self) -> &str;
32    /// Plural display name of the resource.
33    fn plural_name(&self) -> &str;
34    /// URL slug for the resource.
35    fn slug(&self) -> &str;
36    /// Icon for the resource in the dashboard (default: "box").
37    fn icon(&self) -> &str { "box" }
38    /// Columns to show in the list view.
39    fn list_columns(&self) -> Vec<Column>;
40    /// Fields to show in the create/edit form.
41    fn form_fields(&self) -> Vec<FormField>;
42    /// Fields that should be used for the global search.
43    fn searchable_fields(&self) -> Vec<&str> { vec![] }
44    /// Whether the resource can be created.
45    fn can_create(&self) -> bool { true }
46    /// Whether the resource can be deleted.
47    fn can_delete(&self) -> bool { true }
48
49    /// List records based on the provided query.
50    async fn list(&self, query: ListQuery) -> Result<ListResult, AdminError>;
51    /// Retrieve a single record by its ID.
52    async fn get(&self, id: &str) -> Result<serde_json::Value, AdminError>;
53    /// Create a new record.
54    async fn create(&self, data: HashMap<String, serde_json::Value>) -> Result<serde_json::Value, AdminError>;
55    /// Update an existing record.
56    async fn update(&self, id: &str, data: HashMap<String, serde_json::Value>) -> Result<serde_json::Value, AdminError>;
57    /// Delete a record.
58    async fn delete(&self, id: &str) -> Result<(), AdminError>;
59    
60    /// Optional hook to validate data before saving.
61    async fn validate(
62        &self, 
63        _data: &HashMap<String, serde_json::Value>
64    ) -> Result<(), HashMap<String, String>> { Ok(()) }
65
66    /// Return a serializable summary of the resource.
67    fn info(&self, prefix: &str) -> ResourceInfo {
68        ResourceInfo {
69            name: self.name().to_string(),
70            plural_name: self.plural_name().to_string(),
71            slug: self.slug().to_string(),
72            icon: self.icon().to_string(),
73            path_list: format!("{}/{}/", prefix, self.slug()),
74            path_new: format!("{}/{}/new", prefix, self.slug()),
75            path_edit: format!("{}/{}/:id/edit", prefix, self.slug()),
76            path_delete: format!("{}/{}/:id/delete", prefix, self.slug()),
77        }
78    }
79}