feat(#448): schema-driven config UI with category tabs, search, typed inputs

Closes #448

Replaced the raw YAML editor with a full schema-driven config management UI
matching the dashboard's ConfigPage experience.

### New API endpoints (HermesApiService)
- GET /api/config — load structured config
- GET /api/config/schema — load schema with field types + categories  
- GET /api/config/defaults — load defaults for reset
- PUT /api/config — save config (deep-merged on backend)

### Data models
- ConfigSchemaResponse — wraps fields + category_order
- SchemaField — type, description, category, options
- ConfigUpdateRequest — config map + optional profile

### ConfigViewModel
- Loads config + schema + defaults + path on init
- Tracks pending changes as dot-path → JsonElement map
- Builds nested JSON changeset for the save API
- YAML mode toggle with raw YAML load/save
- Per-category reset to defaults

### ConfigScreen
- Category tabs with field-count badges
- Search filtering across key, label, description, category
- Typed inputs: boolean toggles, select dropdowns, number inputs
- Modified highlighting with primaryContainer tint
- YAML ↔ Form mode toggle
- Sticky save indicator with pending-change count
This commit is contained in:
M57 authored and GitHub committed 2026-07-03 08:39:35 +03:00
1 parent d875c8a040
commit efb8e528ef
5 files changed
+962 -89

No files matched your search

@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import com.google.gson.JsonElement
data class RawConfigResponse(
val path: String?,
val yaml: String?,
@@ -9,3 +11,20 @@ data class UpdateRawConfigRequest(
val yaml_text: String,
val profile: String? = null,
)
data class ConfigSchemaResponse(
val fields: Map<String, SchemaField>,
val category_order: List<String>,
)
data class SchemaField(
val type: String,
val description: String? = null,
val category: String? = null,
val options: List<String>? = null,
)
data class ConfigUpdateRequest(
val config: Map<String, JsonElement>,
val profile: String? = null,
)