feat: implement plugin architecture and application settings with Svelte UI

- Added plugin base and loader for backend extensibility
- Implemented application settings management with config persistence
- Created Svelte-based frontend with Dashboard and Settings pages
- Added API routes for plugins, tasks, and settings
- Updated documentation and specifications
- Improved project structure and developer tools
This commit is contained in:
2025-12-20 20:48:18 +03:00
parent ce703322c2
commit 2d8cae563f
98 changed files with 7894 additions and 5021 deletions

172
docs/plugin_dev.md Normal file → Executable file
View File

@@ -1,87 +1,87 @@
# Plugin Development Guide
This guide explains how to create new plugins for the Superset Tools application.
## 1. Plugin Structure
A plugin is a single Python file located in the `backend/src/plugins/` directory. Each plugin file must contain a class that inherits from `PluginBase`.
## 2. Implementing `PluginBase`
The `PluginBase` class is an abstract base class that defines the interface for all plugins. You must implement the following properties and methods:
- **`id`**: A unique string identifier for your plugin (e.g., `"my-cool-plugin"`).
- **`name`**: A human-readable name for your plugin (e.g., `"My Cool Plugin"`).
- **`description`**: A brief description of what your plugin does.
- **`version`**: The version of your plugin (e.g., `"1.0.0"`).
- **`get_schema()`**: A method that returns a JSON schema dictionary defining the input parameters for your plugin. This schema is used to automatically generate a form in the frontend.
- **`execute(params: Dict[str, Any])`**: An `async` method that contains the main logic of your plugin. The `params` argument is a dictionary containing the input data from the user, validated against the schema you defined.
## 3. Example Plugin
Here is an example of a simple "Hello World" plugin:
```python
# backend/src/plugins/hello.py
# [DEF:HelloWorldPlugin:Plugin]
# @SEMANTICS: hello, world, example, plugin
# @PURPOSE: A simple "Hello World" plugin example.
# @LAYER: Domain (Plugin)
# @RELATION: Inherits from PluginBase
# @PUBLIC_API: execute
from typing import Dict, Any
from ..core.plugin_base import PluginBase
class HelloWorldPlugin(PluginBase):
@property
def id(self) -> str:
return "hello-world"
@property
def name(self) -> str:
return "Hello World"
@property
def description(self) -> str:
return "A simple plugin that prints a greeting."
@property
def version(self) -> str:
return "1.0.0"
def get_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "Name",
"description": "The name to greet.",
"default": "World",
}
},
"required": ["name"],
}
async def execute(self, params: Dict[str, Any]):
name = params["name"]
print(f"Hello, {name}!")
```
## 4. Logging
You can use the global logger instance to log messages from your plugin. The logger is available in the `superset_tool.utils.logger` module.
```python
from superset_tool.utils.logger import SupersetLogger
logger = SupersetLogger()
async def execute(self, params: Dict[str, Any]):
logger.info("My plugin is running!")
```
## 5. Testing
# Plugin Development Guide
This guide explains how to create new plugins for the Superset Tools application.
## 1. Plugin Structure
A plugin is a single Python file located in the `backend/src/plugins/` directory. Each plugin file must contain a class that inherits from `PluginBase`.
## 2. Implementing `PluginBase`
The `PluginBase` class is an abstract base class that defines the interface for all plugins. You must implement the following properties and methods:
- **`id`**: A unique string identifier for your plugin (e.g., `"my-cool-plugin"`).
- **`name`**: A human-readable name for your plugin (e.g., `"My Cool Plugin"`).
- **`description`**: A brief description of what your plugin does.
- **`version`**: The version of your plugin (e.g., `"1.0.0"`).
- **`get_schema()`**: A method that returns a JSON schema dictionary defining the input parameters for your plugin. This schema is used to automatically generate a form in the frontend.
- **`execute(params: Dict[str, Any])`**: An `async` method that contains the main logic of your plugin. The `params` argument is a dictionary containing the input data from the user, validated against the schema you defined.
## 3. Example Plugin
Here is an example of a simple "Hello World" plugin:
```python
# backend/src/plugins/hello.py
# [DEF:HelloWorldPlugin:Plugin]
# @SEMANTICS: hello, world, example, plugin
# @PURPOSE: A simple "Hello World" plugin example.
# @LAYER: Domain (Plugin)
# @RELATION: Inherits from PluginBase
# @PUBLIC_API: execute
from typing import Dict, Any
from ..core.plugin_base import PluginBase
class HelloWorldPlugin(PluginBase):
@property
def id(self) -> str:
return "hello-world"
@property
def name(self) -> str:
return "Hello World"
@property
def description(self) -> str:
return "A simple plugin that prints a greeting."
@property
def version(self) -> str:
return "1.0.0"
def get_schema(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "Name",
"description": "The name to greet.",
"default": "World",
}
},
"required": ["name"],
}
async def execute(self, params: Dict[str, Any]):
name = params["name"]
print(f"Hello, {name}!")
```
## 4. Logging
You can use the global logger instance to log messages from your plugin. The logger is available in the `superset_tool.utils.logger` module.
```python
from superset_tool.utils.logger import SupersetLogger
logger = SupersetLogger()
async def execute(self, params: Dict[str, Any]):
logger.info("My plugin is running!")
```
## 5. Testing
To test your plugin, simply run the application and navigate to the web UI. Your plugin should appear in the list of available tools.

46
docs/settings.md Normal file
View File

@@ -0,0 +1,46 @@
# Web Application Settings Mechanism
This document describes the settings management system for the Superset Tools application.
## Overview
The settings mechanism allows users to configure multiple Superset environments and global application settings (like backup storage) via the web UI.
## Backend Architecture
### Data Models
Configuration is structured using Pydantic models in `backend/src/core/config_models.py`:
- `Environment`: Represents a Superset instance (URL, credentials).
- `GlobalSettings`: Global application parameters (e.g., `backup_path`).
- `AppConfig`: The root configuration object.
### Configuration Manager
The `ConfigManager` (`backend/src/core/config_manager.py`) handles:
- Persistence to `config.json`.
- CRUD operations for environments.
- Validation and logging.
### API Endpoints
The settings API is available at `/settings`:
- `GET /settings`: Retrieve all settings (passwords are masked).
- `PATCH /settings/global`: Update global settings.
- `GET /settings/environments`: List environments.
- `POST /settings/environments`: Add environment.
- `PUT /settings/environments/{id}`: Update environment.
- `DELETE /settings/environments/{id}`: Remove environment.
- `POST /settings/environments/{id}/test`: Test connection.
## Frontend Implementation
The settings page is located at `frontend/src/pages/Settings.svelte`. It provides forms for managing global settings and Superset environments.
## Integration
Existing plugins and utilities use the `ConfigManager` to fetch configuration:
- `superset_tool/utils/init_clients.py`: Dynamically initializes Superset clients from the configured environments.
- `BackupPlugin`: Uses the configured `backup_path` as the default storage location.