diff --git a/config/config.go b/config/config.go index 9d3c75d8..53b1b0ca 100644 --- a/config/config.go +++ b/config/config.go @@ -210,28 +210,25 @@ func settingsLayoutMeta() map[string]any { } func ensureDefaultNodeSettings(settings map[string]any) { - group, ok := settings["node"].(map[string]any) - if !ok { - group = make(map[string]any) - settings["node"] = group - } - defaults := map[string]string{ "nodeRole": string(NodeRoleMaster), "nodeId": "", "syncInterval": "30", "trafficFlushInterval": "10", } - for key, value := range defaults { - if existing, exists := group[key]; !exists || existing == nil { - // Also check "other" group for backward compatibility - if otherGroup, ok := settings["other"].(map[string]any); ok { - if val, ok := otherGroup[key].(string); ok && val != "" { - group[key] = val - continue - } + + // Ensure both "node" and "other" groups have the defaults for backward + // compatibility. Old code reads from "other", new code reads from "node". + for _, groupName := range []string{"node", "other"} { + group, ok := settings[groupName].(map[string]any) + if !ok { + group = make(map[string]any) + settings[groupName] = group + } + for key, value := range defaults { + if existing, exists := group[key]; !exists || existing == nil { + group[key] = value } - group[key] = value } } } diff --git a/docs/Tasktracking/2026-04-24-node-management-sidebar.md b/docs/Tasktracking/2026-04-24-node-management-sidebar.md index 71a9046e..c62dafd8 100644 --- a/docs/Tasktracking/2026-04-24-node-management-sidebar.md +++ b/docs/Tasktracking/2026-04-24-node-management-sidebar.md @@ -25,6 +25,8 @@ Adding a Node Management sidebar page to the 3x-ui web panel for cluster node vi | 10 | Fix shared MariaDB query for node states | DONE | d5bf2858 | | 11 | Fix node settings not auto-created in x-ui.json | DONE | d733ff2a | | 12 | Fix master heartbeat not visible to workers | DONE | 226bae2b | +| 13 | Fix ensureDefaultNodeSettings to write both "node" and "other" groups | DONE | — | +| 14 | Replace a-descriptions with HTML table (component missing from antd bundle) | DONE | — | ## v1.6.3 Fix Details diff --git a/docs/Tasktracking/2026-04-25-fix-ensuredefaultnodesettings.md b/docs/Tasktracking/2026-04-25-fix-ensuredefaultnodesettings.md new file mode 100644 index 00000000..c56a6378 --- /dev/null +++ b/docs/Tasktracking/2026-04-25-fix-ensuredefaultnodesettings.md @@ -0,0 +1,48 @@ +# 2026-04-25 Fix ensureDefaultNodeSettings and worker node display + +## Problem + +### 1. Test failures in config package +Two tests were failing: +- `TestWriteSettingToJSONCreatesSettingsFileWhenMissing` +- `TestWriteSettingToJSONBackfillsDefaultNodeSettings` + +Both failed with: `expected other group, got ` + +### 2. Worker frontend not showing connected master node +The worker's node management page rendered the card structure but didn't display the +master node information. The `a-descriptions` and `a-descriptions-item` components were +used in the template but were NOT included in the Ant Design Vue bundle (`antd.min.js`). +Vue silently skipped the unregistered components, resulting in an empty card body. + +## Root Cause + +### Test failures +`ensureDefaultNodeSettings()` only wrote defaults to the `"node"` group. Tests expected +the `"other"` group to also have defaults for backward compatibility. + +### Worker node display +Ant Design Vue 2.x uses tree-shaking — only components actually imported during the build +are included in the bundle. `a-descriptions` and `a-descriptions-item` were not imported +in the project's Ant Design Vue build config, so they were missing from `antd.min.js`. +When Vue encounters an unregistered component tag, it silently ignores it. + +## Fix + +### Test failures +Changed `ensureDefaultNodeSettings()` to iterate over both `"node"` and `"other"` groups, +writing defaults to both for backward compatibility. + +### Worker node display +Replaced `a-descriptions` / `a-descriptions-item` with a plain HTML `` that +replicates the same visual layout (label-value pairs with borders). This doesn't depend +on any Ant Design Vue component. + +## Files Changed + +- `config/config.go`: Modified `ensureDefaultNodeSettings()` to write to both groups +- `web/html/nodes.html`: Replaced `a-descriptions` with HTML table + +## Verification + +- `go test -race -shuffle=on ./...` — all PASS diff --git a/web/html/nodes.html b/web/html/nodes.html index f2e77ab3..eaaaafe3 100644 --- a/web/html/nodes.html +++ b/web/html/nodes.html @@ -49,16 +49,36 @@
- - [[ nodes[0].nodeId ]] - - - - [[ nodes[0].lastHeartbeatAt ? formatTime(nodes[0].lastHeartbeatAt) : '-' ]] - [[ nodes[0].lastSyncAt ? formatTime(nodes[0].lastSyncAt) : '-' ]] - [[ nodes[0].lastSeenVersion ]] - [[ nodes[0].lastError || '-' ]] - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ i18n "pages.nodes.nodeId" }}[[ nodes[0].nodeId ]]
{{ i18n "pages.nodes.status" }} + +
{{ i18n "pages.nodes.lastHeartbeat" }}[[ nodes[0].lastHeartbeatAt ? formatTime(nodes[0].lastHeartbeatAt) : '-' ]]
{{ i18n "pages.nodes.lastSync" }}[[ nodes[0].lastSyncAt ? formatTime(nodes[0].lastSyncAt) : '-' ]]
{{ i18n "pages.nodes.syncVersion" }}[[ nodes[0].lastSeenVersion ]]
{{ i18n "pages.nodes.error" }}[[ nodes[0].lastError || '-' ]]