Files
2026-02-09 12:35:27 +03:00

243 lines
5.2 KiB
Markdown

# API Contracts: Superset-Style UX Redesign
**Feature**: 019-superset-ux-redesign
**Date**: 2026-02-09
## Overview
This document defines the API contracts for new endpoints required by the Resource-Centric UI. All endpoints follow existing patterns in the codebase.
## New Endpoints
### 1. Dashboard Hub API
#### GET /api/dashboards
**Purpose**: Fetch list of dashboards from a specific environment for the Dashboard Hub grid.
**Query Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| env_id | string | Yes | Environment ID to fetch dashboards from |
| search | string | No | Filter by title/slug |
**Response**:
```json
{
"dashboards": [
{
"id": "uuid-string",
"title": "Sales Report",
"slug": "sales-2023",
"url": "/superset/dashboard/sales-2023",
"git_status": {
"branch": "main",
"sync_status": "OK" | "DIFF" | null
},
"last_task": {
"task_id": "task-uuid",
"status": "SUCCESS" | "RUNNING" | "ERROR" | "WAITING_INPUT" | null
}
}
]
}
```
**Errors**:
- `404`: Environment not found
- `503`: Superset connection error
---
### 2. Dataset Hub API
#### GET /api/datasets
**Purpose**: Fetch list of datasets from a specific environment for the Dataset Hub grid.
**Query Parameters**:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| env_id | string | Yes | Environment ID to fetch datasets from |
| search | string | No | Filter by table name |
**Response**:
```json
{
"datasets": [
{
"id": "uuid-string",
"table_name": "fact_orders",
"schema": "public",
"database": "Production DB",
"mapped_fields": {
"total": 20,
"mapped": 15
},
"last_task": {
"task_id": "task-uuid",
"status": "SUCCESS" | null
}
}
]
}
```
---
### 3. Activity API
#### GET /api/activity
**Purpose**: Fetch summary of active and recent tasks for the navbar indicator.
**Response**:
```json
{
"active_count": 3,
"recent_tasks": [
{
"task_id": "task-uuid",
"resource_name": "Sales Report",
"resource_type": "dashboard",
"status": "RUNNING",
"started_at": "2026-02-09T10:00:00Z"
}
]
}
```
---
### 4. Consolidated Settings API
#### GET /api/settings
**Purpose**: Fetch all settings categories for the consolidated settings page.
**Response**:
```json
{
"environments": [
{ "id": "1", "name": "Development", "url": "http://dev...", "status": "OK" }
],
"connections": [
{ "id": "1", "name": "Prod Clickhouse", "type": "clickhouse" }
],
"llm": {
"provider": "openai",
"model": "gpt-4",
"enabled": true
},
"logging": {
"level": "INFO",
"task_log_level": "DEBUG",
"belief_scope_enabled": false
}
}
```
---
## WebSocket Events (Existing)
The Task Drawer subscribes to existing WebSocket events:
### task:status
```json
{
"task_id": "uuid",
"status": "RUNNING" | "SUCCESS" | "ERROR" | "WAITING_INPUT"
}
```
### task:log
```json
{
"task_id": "uuid",
"timestamp": "2026-02-09T10:00:00Z",
"level": "INFO",
"source": "plugin",
"message": "Starting migration..."
}
```
### task:input_required
```json
{
"task_id": "uuid",
"input_type": "password" | "mapping_selection",
"prompt": "Enter database password"
}
```
---
## Module Contracts (Semantic Protocol)
### SidebarStore (frontend/src/lib/stores/sidebar.js)
```javascript
// [DEF:SidebarStore:Store]
// @TIER: STANDARD
// @PURPOSE: Manage sidebar visibility and navigation state
// @LAYER: UI
// @INVARIANT: isExpanded state is always synced with localStorage
// @UX_STATE: Idle -> Sidebar visible with current state
// @UX_STATE: Toggling -> Animation plays for 200ms
export const sidebarStore = writable({
isExpanded: true,
activeCategory: 'dashboards',
activeItem: '/dashboards',
isMobileOpen: false
});
export function toggleSidebar() { /* ... */ }
export function setActiveItem(path) { /* ... */ }
// [/DEF:SidebarStore]
```
### TaskDrawerStore (frontend/src/lib/stores/taskDrawer.js)
```javascript
// [DEF:TaskDrawerStore:Store]
// @TIER: CRITICAL
// @PURPOSE: Manage Task Drawer visibility and resource-to-task mapping
// @LAYER: UI
// @INVARIANT: resourceTaskMap always reflects current task associations
// @UX_STATE: Closed -> Drawer hidden, no active task
// @UX_STATE: Open -> Drawer visible, logs streaming
// @UX_STATE: InputRequired -> Interactive form rendered in drawer
export const taskDrawerStore = writable({
isOpen: false,
activeTaskId: null,
resourceTaskMap: {}
});
export function openDrawerForTask(taskId) { /* ... */ }
export function closeDrawer() { /* ... */ }
export function updateResourceTask(resourceId, taskId, status) { /* ... */ }
// [/DEF:TaskDrawerStore]
```
### ActivityStore (frontend/src/lib/stores/activity.js)
```javascript
// [DEF:ActivityStore:Store]
// @TIER: STANDARD
// @PURPOSE: Track active task count for navbar indicator
// @LAYER: UI
// @RELATION: DEPENDS_ON -> WebSocket connection
export const activityStore = derived(taskDrawerStore, ($drawer) => {
const activeCount = Object.values($drawer.resourceTaskMap)
.filter(t => t.status === 'RUNNING').length;
return { activeCount };
});
// [/DEF:ActivityStore]
```