Files
LEDMatrix/docs/PLUGIN_CONFIGURATION_TABS.md
Chuck 62da1d2b09 docs: fix bare /api/plugins paths in PLUGIN_CONFIGURATION_TABS
Found 5 more bare /api/plugins/* paths in PLUGIN_CONFIGURATION_TABS.md
that I missed in the round 2 sweep — they're inside data flow diagrams
and prose ("loaded via /api/plugins/installed", etc.) so the earlier
grep over Markdown code blocks didn't catch them. Fixed all 5 to use
/api/v3/plugins/* (the api_v3 blueprint mount path verified at
web_interface/app.py:144).

Also added a status banner noting that the "Implementation Details"
section references the pre-v3 file layout (web_interface_v2.py,
templates/index_v2.html) which no longer exists. The current
implementation is in web_interface/app.py, blueprints/api_v3.py, and
templates/v3/. Same kind of historical drift I flagged in
PLUGIN_ARCHITECTURE_SPEC.md and the PLUGIN_CUSTOM_ICONS_FEATURE doc.
The user-facing parts of the doc (Overview, Features, Form Generation
Process) are still accurate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:37:52 -04:00

339 lines
9.5 KiB
Markdown

# Plugin Configuration Tabs
> **Status note:** this doc was written during the rollout of the
> per-plugin configuration tab feature. The feature itself is shipped
> and working in the current v3 web interface, but a few file paths
> in the "Implementation Details" section below still reference the
> pre-v3 file layout (`web_interface_v2.py`, `templates/index_v2.html`).
> The current implementation lives in `web_interface/app.py`,
> `web_interface/blueprints/api_v3.py`, and `web_interface/templates/v3/`.
> The user-facing description (Overview, Features, Form Generation
> Process) is still accurate.
## Overview
Each installed plugin now gets its own dedicated configuration tab in the web interface. This provides a clean, organized way to configure plugins without cluttering the main Plugins management tab.
## Features
- **Automatic Tab Generation**: When a plugin is installed, a new tab is automatically created in the web UI
- **JSON Schema-Based Forms**: Configuration forms are automatically generated based on each plugin's `config_schema.json`
- **Type-Safe Inputs**: Form inputs are created based on the JSON Schema type (boolean, number, string, array, enum)
- **Default Values**: All fields show current values or fallback to schema defaults
- **Reset Functionality**: Users can reset all settings to defaults with one click
- **Real-Time Validation**: Input constraints from JSON Schema are enforced (min, max, maxLength, etc.)
## User Experience
### Accessing Plugin Configuration
1. Navigate to the **Plugins** tab to see all installed plugins
2. Click the **Configure** button on any plugin card
3. You'll be automatically taken to that plugin's configuration tab
4. Alternatively, click directly on the plugin's tab button (marked with a puzzle piece icon)
### Configuring a Plugin
1. Open the plugin's configuration tab
2. Modify settings using the generated form
3. Click **Save Configuration**
4. Restart the display service to apply changes
### Plugin Manager vs Per-Plugin Configuration
- **Plugin Manager tab** (second nav row): used for browsing the
Plugin Store, installing plugins, toggling installed plugins on/off,
and updating/uninstalling them
- **Per-plugin tabs** (one per installed plugin, also in the second
nav row): used for configuring that specific plugin's behavior and
settings via a form auto-generated from its `config_schema.json`
## For Plugin Developers
### Requirements
To enable automatic configuration tab generation, your plugin must:
1. Include a `config_schema.json` file
2. Reference it in your `manifest.json`:
```json
{
"id": "your-plugin",
"name": "Your Plugin",
"icon": "fas fa-star", // Optional: Custom tab icon
...
"config_schema": "config_schema.json"
}
```
**Note:** You can optionally specify a custom `icon` for your plugin tab. See [Plugin Custom Icons Guide](PLUGIN_CUSTOM_ICONS.md) for details.
### Supported JSON Schema Types
The form generator supports the following JSON Schema types:
#### Boolean
```json
{
"type": "boolean",
"default": true,
"description": "Enable or disable this feature"
}
```
Renders as: Toggle switch
#### Number / Integer
```json
{
"type": "integer",
"default": 60,
"minimum": 1,
"maximum": 300,
"description": "Update interval in seconds"
}
```
Renders as: Number input with min/max constraints
#### String
```json
{
"type": "string",
"default": "Hello, World!",
"minLength": 1,
"maxLength": 50,
"description": "The message to display"
}
```
Renders as: Text input with length constraints
#### Array
```json
{
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"minItems": 3,
"maxItems": 3,
"default": [255, 255, 255],
"description": "RGB color [R, G, B]"
}
```
Renders as: Text input (comma-separated values)
Example input: `255, 128, 0`
#### Enum (Select)
```json
{
"type": "string",
"enum": ["small", "medium", "large"],
"default": "medium",
"description": "Display size"
}
```
Renders as: Dropdown select
### Example config_schema.json
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "My Plugin Configuration",
"description": "Configure my awesome plugin",
"properties": {
"enabled": {
"type": "boolean",
"default": true,
"description": "Enable or disable this plugin"
},
"message": {
"type": "string",
"default": "Hello!",
"minLength": 1,
"maxLength": 50,
"description": "The message to display"
},
"update_interval": {
"type": "integer",
"default": 60,
"minimum": 1,
"maximum": 3600,
"description": "Update interval in seconds"
},
"color": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"minItems": 3,
"maxItems": 3,
"default": [255, 255, 255],
"description": "RGB color [R, G, B]"
},
"mode": {
"type": "string",
"enum": ["scroll", "static", "fade"],
"default": "scroll",
"description": "Display mode"
}
},
"required": ["enabled"],
"additionalProperties": false
}
```
### Best Practices
1. **Use Descriptive Labels**: The `description` field is shown as help text under each input
2. **Set Sensible Defaults**: Always provide default values that work out of the box
3. **Use Constraints**: Leverage min/max, minLength/maxLength to guide users
4. **Mark Required Fields**: Use the `required` array in your schema
5. **Organize Properties**: List properties in order of importance
### Form Generation Process
1. Web UI loads installed plugins via `/api/v3/plugins/installed`
2. For each plugin, the backend loads its `config_schema.json`
3. Frontend generates a tab button with plugin name
4. Frontend generates a form based on the JSON Schema
5. Current config values from `config.json` are populated
6. When saved, each field is sent to `/api/v3/plugins/config` endpoint
## Implementation Details
### Backend Changes
**File**: `web_interface_v2.py`
- Modified `/api/v3/plugins/installed` endpoint to include `config_schema_data`
- Loads each plugin's `config_schema.json` if it exists
- Returns schema data along with plugin info
### Frontend Changes
**File**: `templates/index_v2.html`
New Functions:
- `generatePluginTabs(plugins)` - Creates tab buttons and content for each plugin
- `generatePluginConfigForm(plugin)` - Generates HTML form from JSON Schema
- `savePluginConfiguration(pluginId)` - Saves form data to backend
- `resetPluginConfig(pluginId)` - Resets all settings to defaults
- `configurePlugin(pluginId)` - Navigates to plugin's tab
### Data Flow
```
Page Load
→ refreshPlugins()
→ /api/v3/plugins/installed
→ Returns plugins with config_schema_data
→ generatePluginTabs()
→ Creates tab buttons
→ Creates tab content
→ generatePluginConfigForm()
→ Reads JSON Schema
→ Creates form inputs
→ Populates current values
User Saves
→ savePluginConfiguration()
→ Reads form data
→ Converts types per schema
→ Sends to /api/v3/plugins/config
→ Updates config.json
→ Shows success notification
```
## Troubleshooting
### Plugin Tab Not Appearing
- Ensure `config_schema.json` exists in plugin directory
- Verify `config_schema` field in `manifest.json`
- Check browser console for errors
- Try refreshing plugins (Plugins tab → Refresh button)
### Form Not Generating Correctly
- Validate your `config_schema.json` against JSON Schema Draft 07
- Check that all properties have a `type` field
- Ensure `default` values match the specified type
- Look for JavaScript errors in browser console
### Configuration Not Saving
- Ensure the plugin is properly installed
- Check that config keys match schema properties
- Verify backend API is accessible
- Check browser network tab for API errors
- Ensure display service is restarted after config changes
## Migration Guide
### For Existing Plugins
If your plugin already has a `config_schema.json`:
1. No changes needed! The tab will be automatically generated.
2. Test the generated form to ensure all fields render correctly.
3. Consider adding more descriptive `description` fields.
If your plugin doesn't have a config schema:
1. Create `config_schema.json` based on your current config structure
2. Add descriptions for each property
3. Set appropriate defaults
4. Add validation constraints (min, max, etc.)
5. Reference the schema in your `manifest.json`
### Backward Compatibility
- Plugins without `config_schema.json` still work normally
- They simply won't have a configuration tab
- Users can still edit config via the Raw JSON editor
- The Configure button will navigate to a tab with a friendly message
## Future Enhancements
Potential improvements for future versions:
- **Advanced Schema Features**: Support for nested objects, conditional fields
- **Visual Validation**: Real-time validation feedback as user types
- **Color Pickers**: Special input for RGB/color array types
- **File Uploads**: Support for image/asset uploads
- **Import/Export**: Save and share plugin configurations
- **Presets**: Quick-switch between saved configurations
- **Documentation Links**: Link schema fields to plugin documentation
## Example Plugins
See these plugins for examples of config schemas:
- `hello-world`: Simple plugin with basic types
- `clock-simple`: Plugin with enum and number types
## Support
For questions or issues:
- Check the main LEDMatrix wiki
- Review plugin documentation
- Open an issue on GitHub
- Join the community Discord