|
| 1 | +"""An app to view the holoviz-mcp configuration using Panel and Panel Material UI best practices. |
| 2 | +
|
| 3 | +- Uses parameter-driven architecture for reactivity and maintainability |
| 4 | +- Uses a Panel template for layout and branding |
| 5 | +- Uses only Panel Material UI components for UI widgets |
| 6 | +- Separates config loading logic from UI logic |
| 7 | +- Responsive and modern design |
| 8 | +""" |
| 9 | + |
| 10 | +import json |
| 11 | + |
| 12 | +import panel as pn |
| 13 | +import panel_material_ui as pmui |
| 14 | +import param |
| 15 | + |
| 16 | +from holoviz_mcp.config.loader import HoloVizMCPConfig |
| 17 | +from holoviz_mcp.config.loader import get_config |
| 18 | +from holoviz_mcp.config.loader import get_config_loader |
| 19 | + |
| 20 | +pn.extension("jsoneditor") |
| 21 | + |
| 22 | + |
| 23 | +class ConfigViewer(param.Parameterized): |
| 24 | + """ |
| 25 | + A Panel Material UI app for viewing holoviz-mcp configuration. |
| 26 | +
|
| 27 | + Features: |
| 28 | + - Parameter-driven reactivity |
| 29 | + - Modern, responsive UI using Panel Material UI |
| 30 | + - Separation of config loading and UI logic |
| 31 | + - Supports dark and light themes |
| 32 | + """ |
| 33 | + |
| 34 | + config_source = param.Selector(objects=["Combined", "Default", "User"], default="Combined", doc="Which configuration to show") |
| 35 | + dark_theme = param.Boolean(default=False, doc="Use dark theme for the JSON editor", allow_refs=True) |
| 36 | + |
| 37 | + def __init__(self, **params): |
| 38 | + """ |
| 39 | + Initialize the ConfigViewer. |
| 40 | +
|
| 41 | + Loads environment config and config loader. |
| 42 | + """ |
| 43 | + super().__init__(**params) |
| 44 | + self._env_config = HoloVizMCPConfig.from_environment() |
| 45 | + self._loader = get_config_loader() |
| 46 | + |
| 47 | + @param.depends("config_source") |
| 48 | + def _config_json(self): |
| 49 | + """Get the selected configuration as a JSON string.""" |
| 50 | + if self.config_source == "Combined": |
| 51 | + return get_config().model_dump_json(indent=2) |
| 52 | + elif self.config_source == "Default": |
| 53 | + default_config_file = self._env_config.default_dir / "config.yaml" |
| 54 | + default_config = self._loader._load_yaml_file(default_config_file) |
| 55 | + return json.dumps(default_config, indent=2) |
| 56 | + elif self.config_source == "User": |
| 57 | + user_config_file = self._env_config.user_dir / "config.yaml" |
| 58 | + user_config = self._loader._load_yaml_file(user_config_file) |
| 59 | + return json.dumps(user_config, indent=2) |
| 60 | + return json.dumps({"error": "Unknown config source"}, indent=2) |
| 61 | + |
| 62 | + @param.depends("dark_theme") |
| 63 | + def _theme(self): |
| 64 | + """Get the theme for the JSON editor ('dark' or 'light').""" |
| 65 | + return "dark" if self.dark_theme else "light" |
| 66 | + |
| 67 | + def view(self): |
| 68 | + """Get the main view for the configuration viewer app.""" |
| 69 | + selector = pmui.RadioButtonGroup.from_param( |
| 70 | + self.param.config_source, |
| 71 | + color="primary", |
| 72 | + orientation="horizontal", |
| 73 | + sx={"mb": 2}, |
| 74 | + ) |
| 75 | + json_pane = pn.pane.JSON( |
| 76 | + self._config_json, |
| 77 | + name="holoviz-mcp config", |
| 78 | + theme=self._theme, |
| 79 | + sizing_mode="stretch_width", |
| 80 | + ) |
| 81 | + card = pmui.Paper( |
| 82 | + pmui.Column( |
| 83 | + pmui.Typography( |
| 84 | + "HoloViz MCP Configuration Viewer", |
| 85 | + variant="h5", |
| 86 | + sx={"fontWeight": 700, "mb": 2}, |
| 87 | + ), |
| 88 | + selector, |
| 89 | + json_pane, |
| 90 | + ), |
| 91 | + elevation=3, |
| 92 | + sx={"maxWidth": "900px", "margin": "auto", "padding": "32px"}, |
| 93 | + ) |
| 94 | + return pmui.Container(card) |
| 95 | + |
| 96 | + def _update_source(self, selector): |
| 97 | + """Update the config source from the selector widget.""" |
| 98 | + self.config_source = selector.value |
| 99 | + |
| 100 | + @classmethod |
| 101 | + def create_app(cls): |
| 102 | + """Create and return the Panel Material UI app page.""" |
| 103 | + viewer = cls() |
| 104 | + page = pmui.Page( |
| 105 | + title="HoloViz MCP Configuration Viewer", |
| 106 | + main=[viewer.view()], |
| 107 | + ) |
| 108 | + viewer.dark_theme = page.param.dark_theme |
| 109 | + return page |
| 110 | + |
| 111 | + |
| 112 | +if __name__ == "__main__": |
| 113 | + ConfigViewer.create_app().show(port=5007, open=True, dev=True) |
| 114 | +elif pn.state.served: |
| 115 | + ConfigViewer.create_app().servable() |
0 commit comments