Skip to content

Commit 76d24d0

Browse files
sarg3ntclaude
andcommitted
fix(onboarding): address Copilot review on PR #57
- ui.Toggle: default an empty value to "on" inside the component (via toggleValue helper) so single-boolean callers submit a meaningful form value matching the HTML default. Previously the component emitted value="" verbatim, so r.FormValue(name) == "on" was always false even when checked. Multi-select groups still pass an explicit non-empty value as before. - InjectIntegrationStatus: restore fail-open semantics on box-gear DB load errors. Previously this PR set a partial gear status/order context (system gears only) on error, collapsing the sidebar instead of falling back to the default full-rendering branch. Now box-gear errors short-circuit before any context is set, matching the original behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 02c54d2 commit 76d24d0

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

gearbox/internal/framework/handler/handler.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,22 @@ func (h *Handler) InjectIntegrationStatus(next http.Handler) http.Handler {
221221
if boxID := h.getDefaultServerID(); boxID != "" {
222222
integrations, err := h.db.GetGears(boxID)
223223
if err != nil {
224-
h.logger.Error("failed to get integrations for sidebar", "error", err)
225-
} else {
226-
for _, i := range integrations {
227-
status[i.Name] = i.Enabled
228-
orderedIntegrations = append(orderedIntegrations, auth.SidebarIntegration{
229-
Name: i.Name,
230-
Enabled: i.Enabled,
231-
SortOrder: i.SortOrder,
232-
})
233-
}
224+
// Fail-open: a partial gear list could collapse the sidebar
225+
// to system-gears-only, hiding box features the user
226+
// actually has. Leave the gear-status/order context unset
227+
// so OrderedIntegrationLinks falls back to its default
228+
// (full) rendering branch.
229+
h.logger.Error("failed to get box integrations for sidebar", "error", err)
230+
next.ServeHTTP(w, r.WithContext(ctx))
231+
return
232+
}
233+
for _, i := range integrations {
234+
status[i.Name] = i.Enabled
235+
orderedIntegrations = append(orderedIntegrations, auth.SidebarIntegration{
236+
Name: i.Name,
237+
Enabled: i.Enabled,
238+
SortOrder: i.SortOrder,
239+
})
234240
}
235241
} else {
236242
// No box configured — explicitly mark box-scoped gears off so

gearbox/internal/framework/ui/toggle.templ

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
package ui
22

3+
// toggleValue defaults an empty value to "on" so the underlying checkbox
4+
// submits a non-empty form value when checked. This matches the HTML
5+
// default for a value-less checkbox and keeps `r.FormValue(name) == "on"`
6+
// callers working without forcing every site to pass an explicit value.
7+
func toggleValue(v string) string {
8+
if v == "" {
9+
return "on"
10+
}
11+
return v
12+
}
13+
314
// Toggle creates a switch/toggle input component.
415
//
516
// id: unique identifier for the input
617
// name: form field name
7-
// value: form value submitted when checked (empty string → defaults to "on")
18+
// value: form value submitted when checked. If empty, defaults to "on"
19+
// (the HTML default for a checkbox without a value attribute). Pass
20+
// a unique non-empty value when multiple toggles share a name
21+
// (multi-select checkbox group).
822
// checked: initial state
923
// disabled: whether the toggle is disabled
1024
//
@@ -17,7 +31,7 @@ templ Toggle(id string, name string, value string, checked bool, disabled bool)
1731
type="checkbox"
1832
id={ id }
1933
name={ name }
20-
value={ value }
34+
value={ toggleValue(value) }
2135
class="sr-only peer"
2236
checked?={ checked }
2337
disabled?={ disabled }

0 commit comments

Comments
 (0)