complete_plugin/
complete_plugin.rs

1//! Example of creating a complete plugin manifest with UI pages.
2
3use orbis_plugin_api::*;
4use std::collections::HashMap;
5
6fn main() {
7    // Create a simple plugin manifest
8    let manifest = PluginManifest {
9        name: "example-plugin".to_string(),
10        version: "1.0.0".to_string(),
11        description: "An example plugin demonstrating the API".to_string(),
12        author: Some("Plugin Developer".to_string()),
13        homepage: Some("https://example.com".to_string()),
14        license: Some("MIT".to_string()),
15        min_orbis_version: Some("0.1.0".to_string()),
16        dependencies: vec![],
17        permissions: vec![
18            PluginPermission::DatabaseRead,
19            PluginPermission::Network,
20        ],
21        routes: vec![
22            PluginRoute {
23                method: "GET".to_string(),
24                path: "/api/data".to_string(),
25                handler: "get_data".to_string(),
26                description: Some("Fetch data from the plugin".to_string()),
27                requires_auth: true,
28                permissions: vec![],
29                rate_limit: Some(60),
30            },
31        ],
32        pages: vec![create_dashboard_page()],
33        wasm_entry: Some("plugin.wasm".to_string()),
34        config: serde_json::json!({}),
35    };
36
37    // Validate the manifest
38    match manifest.validate() {
39        Ok(()) => println!("✓ Manifest is valid"),
40        Err(e) => eprintln!("✗ Manifest validation failed: {}", e),
41    }
42
43    // Serialize to JSON
44    match serde_json::to_string_pretty(&manifest) {
45        Ok(json) => println!("\nManifest JSON:\n{}", json),
46        Err(e) => eprintln!("Failed to serialize manifest: {}", e),
47    }
48}
49
50fn create_dashboard_page() -> PageDefinition {
51    let mut state = HashMap::new();
52    
53    // Define state fields
54    state.insert(
55        "loading".to_string(),
56        StateFieldDefinition {
57            field_type: StateFieldType::Boolean,
58            default: Some(serde_json::json!(false)),
59            nullable: false,
60            description: Some("Loading state".to_string()),
61        },
62    );
63    
64    state.insert(
65        "data".to_string(),
66        StateFieldDefinition {
67            field_type: StateFieldType::Array,
68            default: Some(serde_json::json!([])),
69            nullable: false,
70            description: Some("Data from API".to_string()),
71        },
72    );
73
74    PageDefinition {
75        route: "/dashboard".to_string(),
76        title: "Dashboard".to_string(),
77        icon: Some("LayoutDashboard".to_string()),
78        description: Some("Plugin dashboard with data visualization".to_string()),
79        show_in_menu: true,
80        menu_order: 0,
81        parent_route: None,
82        requires_auth: true,
83        permissions: vec![],
84        roles: vec![],
85        state,
86        computed: HashMap::new(),
87        sections: vec![
88            // Container with header
89            ComponentSchema {
90                component_type: "Container".to_string(),
91                id: Some("main".to_string()),
92                class_name: Some("p-6".to_string()),
93                style: None,
94                visible: None,
95                children: vec![
96                    // Header
97                    ComponentSchema {
98                        component_type: "Text".to_string(),
99                        id: None,
100                        class_name: Some("text-2xl font-bold mb-4".to_string()),
101                        style: None,
102                        visible: None,
103                        children: vec![],
104                        events: None,
105                        props: {
106                            let mut props = HashMap::new();
107                            props.insert("text".to_string(), serde_json::json!("Dashboard"));
108                            props
109                        },
110                    },
111                    // Loading indicator
112                    ComponentSchema {
113                        component_type: "Text".to_string(),
114                        id: None,
115                        class_name: None,
116                        style: None,
117                        visible: Some(serde_json::json!("${state.loading}")),
118                        children: vec![],
119                        events: None,
120                        props: {
121                            let mut props = HashMap::new();
122                            props.insert("text".to_string(), serde_json::json!("Loading..."));
123                            props
124                        },
125                    },
126                    // Data table
127                    ComponentSchema {
128                        component_type: "Table".to_string(),
129                        id: Some("dataTable".to_string()),
130                        class_name: None,
131                        style: None,
132                        visible: Some(serde_json::json!("${!state.loading}")),
133                        children: vec![],
134                        events: None,
135                        props: {
136                            let mut props = HashMap::new();
137                            props.insert("dataSource".to_string(), serde_json::json!("state:data"));
138                            props.insert("columns".to_string(), serde_json::json!([
139                                {
140                                    "key": "id",
141                                    "label": "ID",
142                                    "sortable": true
143                                },
144                                {
145                                    "key": "name",
146                                    "label": "Name",
147                                    "sortable": true
148                                },
149                                {
150                                    "key": "value",
151                                    "label": "Value",
152                                    "sortable": false
153                                }
154                            ]));
155                            props
156                        },
157                    },
158                ],
159                events: None,
160                props: HashMap::new(),
161            },
162        ],
163        actions: HashMap::new(),
164        hooks: Some(PageLifecycleHooks {
165            on_mount: vec![
166                Action::CallApi {
167                    name: Some("fetchData".to_string()),
168                    api: "/api/plugins/example-plugin/api/data".to_string(),
169                    method: Some("GET".to_string()),
170                    args_from_state: vec![],
171                    map_args: vec![],
172                    body: None,
173                    on_success: vec![
174                        Action::UpdateState {
175                            path: "data".to_string(),
176                            value: None,
177                            from: Some("response.data".to_string()),
178                            merge: false,
179                        },
180                    ],
181                    on_error: vec![
182                        Action::ShowToast {
183                            level: ToastLevel::Error,
184                            message: "Failed to load data".to_string(),
185                            title: Some("Error".to_string()),
186                            duration: Some(5000),
187                        },
188                    ],
189                    on_finally: vec![
190                        Action::UpdateState {
191                            path: "loading".to_string(),
192                            value: Some(serde_json::json!(false)),
193                            from: None,
194                            merge: false,
195                        },
196                    ],
197                },
198            ],
199            on_unmount: vec![],
200            on_params_change: vec![],
201            on_query_change: vec![],
202        }),
203        dialogs: vec![],
204    }
205}