pinakes-ui: integrate plugin registry into app navigation and routing
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7c4593d93693bf08555a0b5f89a67aea6a6a6964
This commit is contained in:
parent
de913e54bc
commit
6e442065b1
2 changed files with 196 additions and 40 deletions
|
|
@ -19,7 +19,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use pinakes_plugin_api::UiPage;
|
||||
use pinakes_plugin_api::{UiPage, UiWidget};
|
||||
|
||||
use crate::client::ApiClient;
|
||||
|
||||
|
|
@ -39,15 +39,17 @@ impl PluginPage {
|
|||
}
|
||||
}
|
||||
|
||||
/// Registry of all plugin-provided UI pages
|
||||
/// Registry of all plugin-provided UI pages and widgets
|
||||
///
|
||||
/// This is typically stored as a context value in the Dioxus tree.
|
||||
/// This is typically stored as a signal in the Dioxus tree.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PluginRegistry {
|
||||
/// API client for fetching pages from server
|
||||
client: ApiClient,
|
||||
/// Cached pages: (plugin_id, page_id) -> PluginPage
|
||||
pages: HashMap<(String, String), PluginPage>,
|
||||
/// Cached widgets: (plugin_id, widget_id) -> UiWidget
|
||||
widgets: Vec<(String, UiWidget)>,
|
||||
/// Last refresh timestamp
|
||||
last_refresh: Option<chrono::DateTime<chrono::Utc>>,
|
||||
}
|
||||
|
|
@ -58,17 +60,15 @@ impl PluginRegistry {
|
|||
Self {
|
||||
client,
|
||||
pages: HashMap::new(),
|
||||
widgets: Vec::new(),
|
||||
last_refresh: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new registry with pre-loaded pages
|
||||
pub fn with_pages(
|
||||
client: ApiClient,
|
||||
pages: Vec<(String, String, UiPage)>,
|
||||
) -> Self {
|
||||
pub fn with_pages(client: ApiClient, pages: Vec<(String, UiPage)>) -> Self {
|
||||
let mut registry = Self::new(client);
|
||||
for (plugin_id, _page_id, page) in pages {
|
||||
for (plugin_id, page) in pages {
|
||||
registry.register_page(plugin_id, page);
|
||||
}
|
||||
registry
|
||||
|
|
@ -93,6 +93,16 @@ impl PluginRegistry {
|
|||
.get(&(plugin_id.to_string(), page_id.to_string()))
|
||||
}
|
||||
|
||||
/// Register a widget from a plugin
|
||||
pub fn register_widget(&mut self, plugin_id: String, widget: UiWidget) {
|
||||
self.widgets.push((plugin_id, widget));
|
||||
}
|
||||
|
||||
/// Get all widgets (for use with WidgetContainer)
|
||||
pub fn all_widgets(&self) -> Vec<(String, UiWidget)> {
|
||||
self.widgets.clone()
|
||||
}
|
||||
|
||||
/// Get all pages
|
||||
pub fn all_pages(&self) -> Vec<&PluginPage> {
|
||||
self.pages.values().collect()
|
||||
|
|
@ -122,6 +132,7 @@ impl PluginRegistry {
|
|||
match self.client.get_plugin_ui_pages().await {
|
||||
Ok(pages) => {
|
||||
self.pages.clear();
|
||||
self.widgets.clear();
|
||||
for (plugin_id, page) in pages {
|
||||
self.register_page(plugin_id, page);
|
||||
}
|
||||
|
|
@ -245,4 +256,103 @@ mod tests {
|
|||
assert_eq!(routes[0].1, "page1");
|
||||
assert_eq!(routes[0].2, "/plugins/plugin1/page1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_register_widget_and_all_widgets() {
|
||||
let client = ApiClient::default();
|
||||
let mut registry = PluginRegistry::new(client);
|
||||
|
||||
let widget: UiWidget = serde_json::from_value(serde_json::json!({
|
||||
"id": "my-widget",
|
||||
"target": "library_header",
|
||||
"content": { "type": "badge", "text": "hello", "variant": "default" }
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
assert!(registry.all_widgets().is_empty());
|
||||
registry.register_widget("test-plugin".to_string(), widget.clone());
|
||||
let widgets = registry.all_widgets();
|
||||
assert_eq!(widgets.len(), 1);
|
||||
assert_eq!(widgets[0].0, "test-plugin");
|
||||
assert_eq!(widgets[0].1.id, "my-widget");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_pages_builds_registry() {
|
||||
let client = ApiClient::default();
|
||||
let pages = vec![
|
||||
("plugin1".to_string(), create_test_page("page1", "Page 1")),
|
||||
("plugin2".to_string(), create_test_page("page2", "Page 2")),
|
||||
];
|
||||
|
||||
let registry = PluginRegistry::with_pages(client, pages);
|
||||
assert_eq!(registry.len(), 2);
|
||||
assert!(registry.get_page("plugin1", "page1").is_some());
|
||||
assert!(registry.get_page("plugin2", "page2").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_register_page_overwrites_same_key() {
|
||||
let client = ApiClient::default();
|
||||
let mut registry = PluginRegistry::new(client);
|
||||
|
||||
registry
|
||||
.register_page("plugin1".to_string(), create_test_page("p", "Original"));
|
||||
registry
|
||||
.register_page("plugin1".to_string(), create_test_page("p", "Updated"));
|
||||
|
||||
assert_eq!(registry.len(), 1);
|
||||
assert_eq!(
|
||||
registry.get_page("plugin1", "p").unwrap().page.title,
|
||||
"Updated"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_registry_is_empty() {
|
||||
let registry = PluginRegistry::default();
|
||||
assert!(registry.is_empty());
|
||||
assert_eq!(registry.len(), 0);
|
||||
assert!(registry.last_refresh().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_pages_returns_references() {
|
||||
let client = ApiClient::default();
|
||||
let mut registry = PluginRegistry::new(client);
|
||||
registry.register_page("p1".to_string(), create_test_page("a", "A"));
|
||||
registry.register_page("p2".to_string(), create_test_page("b", "B"));
|
||||
|
||||
let pages = registry.all_pages();
|
||||
assert_eq!(pages.len(), 2);
|
||||
let titles: Vec<&str> =
|
||||
pages.iter().map(|p| p.page.title.as_str()).collect();
|
||||
assert!(titles.contains(&"A"));
|
||||
assert!(titles.contains(&"B"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_different_plugins_same_page_id_both_stored() {
|
||||
let client = ApiClient::default();
|
||||
let mut registry = PluginRegistry::new(client);
|
||||
|
||||
registry.register_page(
|
||||
"plugin-a".to_string(),
|
||||
create_test_page("home", "A Home"),
|
||||
);
|
||||
registry.register_page(
|
||||
"plugin-b".to_string(),
|
||||
create_test_page("home", "B Home"),
|
||||
);
|
||||
|
||||
assert_eq!(registry.len(), 2);
|
||||
assert_eq!(
|
||||
registry.get_page("plugin-a", "home").unwrap().page.title,
|
||||
"A Home"
|
||||
);
|
||||
assert_eq!(
|
||||
registry.get_page("plugin-b", "home").unwrap().page.title,
|
||||
"B Home"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue