Implement plugin dynamic settings routes architecture

Plugins can now register their settings pages dynamically via get_settings_routes()
hook, eliminating hardcoded imports that break lean builds.

Backend:
- Add get_settings_routes() hook to BasePlugin (shopdb/plugins/base.py)
- Implement in ComputersPlugin for Operating Systems management
- Add /api/plugins/settings-routes endpoint to expose plugin routes

Frontend:
- ModelCatalogHub fetches plugin routes and dynamically adds them via router.addRoute()
- Tabs render dynamically from pluginTabs ref
- Components lazy-load when clicked

Benefits:
- Lean builds work without manual route exclusions
- Plugins self-contain their UI extensions
- No core code changes needed when adding plugin settings pages
- Follows plugin architecture best practices

Fixes TODO from commit a03fd3de4f

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Proudlock
2026-09-11 16:49:10 -04:00
parent 4943e182c3
commit fe09d2745e
5 changed files with 95 additions and 15 deletions

View File

@@ -42,6 +42,30 @@ def list_enabled_plugins():
return success_response(sorted(names))
@plugins_bp.route('/settings-routes', methods=['GET'])
@jwt_required(optional=True)
def get_plugin_settings_routes():
"""Return settings routes contributed by all enabled plugins.
Plugins can register routes to add tabs/pages to settings hubs like
Model Catalog, Asset Config, etc. Frontend router merges these dynamically.
Returns: { routes: [{hub, path, name, tab, component}, ...] }
"""
pm = current_app.extensions.get('plugin_manager')
if not pm:
return success_response({'routes': []})
routes = []
for plugin in pm.get_enabled_plugin_instances():
if hasattr(plugin, 'get_settings_routes'):
plugin_routes = plugin.get_settings_routes()
if plugin_routes:
routes.extend(plugin_routes)
return success_response({'routes': routes})
@plugins_bp.route('/<name>', methods=['PUT'])
@jwt_required()
@require_role('admin')

View File

@@ -129,6 +129,30 @@ class BasePlugin(ABC):
"""
return []
def get_settings_routes(self) -> List[Dict]:
"""Frontend routes this plugin adds to settings pages.
Returns a list of route configurations for the plugin's settings pages.
Each route is a dict with:
hub - settings hub to attach to ('model-catalog', 'asset-config', etc.)
path - route path relative to hub (e.g. 'operatingsystems')
name - unique route name (e.g. 'model-catalog-os')
tab - tab label shown in hub UI (e.g. 'Operating Systems')
component- path to Vue component (e.g. 'plugins/<name>/frontend/views/<Component>.vue')
Example:
return [{
'hub': 'model-catalog',
'path': 'operatingsystems',
'name': 'model-catalog-os',
'tab': 'Operating Systems',
'component': 'plugins/computers/frontend/views/OperatingSystemsList.vue'
}]
Return [] (default) if the plugin adds no settings pages.
"""
return []
def get_settings_defaults(self) -> List[Dict]:
"""Declare the Setting rows this plugin owns.