Skip to content

fix(dashboard): template picker defensive fixes (handleApply + vacuous-truth)#1015

Open
yasinBursali wants to merge 2 commits intoLight-Heart-Labs:mainfrom
yasinBursali:fix/dashboard-template-picker-defensive
Open

fix(dashboard): template picker defensive fixes (handleApply + vacuous-truth)#1015
yasinBursali wants to merge 2 commits intoLight-Heart-Labs:mainfrom
yasinBursali:fix/dashboard-template-picker-defensive

Conversation

@yasinBursali
Copy link
Copy Markdown
Contributor

@yasinBursali yasinBursali commented Apr 23, 2026

✅ Rebased on current main 2026-04-28

#1003 has merged. The PR diff is now exactly the 2-line "Our delta" view below: lib/templates.js (+1 line) and TemplatePicker.jsx (1 line modified).

What

Two small defensive fixes in template-related dashboard code:

  • lib/templates.js getTemplateStatus: add early-return if (services.length === 0) return 'available' guarding against [].every(s => s === 'enabled') returning true (vacuous truth). Without this, templates with services: [] get misclassified as 'applied' — silently hidden from the Extensions page (filter drops 'applied') and rendered as a disabled green "Applied" card in the setup wizard added by fix(dashboard,dashboard-api): sentinel-based setup wizard success detection #1003.
  • TemplatePicker.jsx handleApply: replace const data = await res.json().catch(() => ({})) with const data = await res.json(). The silent .catch(() => ({})) swallowed malformed server responses and fabricated an empty data object → UI showed a fake "already active" state. The outer try/catch at line 159 already sets setError('Failed to apply template') — letting parse errors bubble there gives users a visible error state.

Our delta

Two files, two lines:

  • dashboard/src/lib/templates.js: + if (services.length === 0) return 'available'
  • dashboard/src/components/TemplatePicker.jsx: - const data = await res.json().catch(() => ({}))+ const data = await res.json()

Testing

  • Verified outer catch (err) { setError(...) } at TemplatePicker.jsx:159 shows a user-visible error path
  • Vacuous-truth early-return placed BEFORE the .every() check — empty-services templates now correctly return 'available'
  • Pre-commit hooks clean
  • ESLint clean on touched files
  • Unit tests for these two code paths — filing as a fork follow-up issue (not blocking)

Platform Impact

  • All three platforms: browser-side React/JS; dashboard is served via nginx, same behavior on macOS/Linux/Windows (WSL2).

@Lightheartdevs
Copy link
Copy Markdown
Collaborator

Audit follow-up: keep draft and rebase after #1003.

The defensive TemplatePicker/error handling ideas are useful, but #1003 is now on main, and this draft needs to be restacked against that sentinel-based setup flow. Please rebase, keep only the still-needed UI defensive fixes, and rerun the dashboard tests before marking ready.

yasinBursali and others added 2 commits April 28, 2026 04:53
getTemplateStatus used statuses.every(s => s === 'enabled'), which
returns true for empty arrays (vacuous truth). Templates with
services: [] were incorrectly classified 'applied' — invisible on the
Extensions page (filter drops 'applied') and rendered as a disabled
green 'Applied' card in the setup wizard.

Early-return 'available' when services.length === 0 before the
.every() check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The silent .catch(() => ({})) swallowed malformed server responses
and fabricated an empty data object, showing a fake 'already active'
UI state when the backend actually returned something unparseable.

Drop the inline .catch so res.json() failures propagate to the
existing outer try/catch, which surfaces a user-visible
'Failed to apply template' error via setError.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yasinBursali yasinBursali force-pushed the fix/dashboard-template-picker-defensive branch from e7887cc to 479ec12 Compare April 28, 2026 01:53
@yasinBursali
Copy link
Copy Markdown
Contributor Author

Rebased on current main (#1003 has merged). Diff collapsed to exactly the 2-line delta the description always promised — lib/templates.js early-return + TemplatePicker.jsx .catch(() => ({})) removal. ESLint clean on touched files. Description updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants