feat: add REST dashboard web shell - #3
Conversation
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR adds the ChangesMeticulous Client History Types
Web Dashboard Workspace
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
packages/meticulous-client/src/index.ts (1)
73-73: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAvoid widening
getCurrentHistory()back toJsonObject.Line 73 effectively drops the new history typing if
HistoryEntryalready extendsJsonObject. If/history/currentis structured, returnPromise<HistoryEntry>; otherwise model the alternate payload with its own interface instead of a catch-all supertype.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/meticulous-client/src/index.ts` at line 73, The getCurrentHistory() contract is being widened back to a catch-all JsonObject, which undoes the new history typing. Update the method in index.ts to return Promise<HistoryEntry> if /history/current is always structured, or introduce a separate explicit interface for any alternate payload instead of using a union with JsonObject. Keep the change aligned with the existing HistoryEntry type so callers get the intended specific history shape.apps/web/src/app.tsx (1)
88-194: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAbort stale machine reads in the cleanup path.
Cleanup only flips
isCancelled, so unmounted or reconfigured instances still leave four browser requests running against the machine until they finish. For a direct browser-to-machine dashboard, canceling those reads is a better default than only ignoring their responses.Proposed change
let isCancelled = false; - const client = createDashboardClient(config.meticulousBaseUrl); + const controller = new AbortController(); + const client = createDashboardClient( + config.meticulousBaseUrl, + (input, init) => fetch(input, { ...init, signal: controller.signal }), + ); @@ return () => { isCancelled = true; + controller.abort(); };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/app.tsx` around lines 88 - 194, The cleanup in the `useEffect` inside `App` only sets `isCancelled`, so the `getMachine`, `getSettings`, `getHistory`, and `getLastProfile` requests keep running after unmount or base URL changes. Add request cancellation to the `createDashboardClient` flow and abort those in-flight reads from the effect cleanup, while still keeping the existing `isCancelled` guards around the state updates.apps/web/src/lib/create-dashboard-client.ts (1)
1-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winImport the client through its package entrypoint.
Reaching into
packages/meticulous-client/src/indexcouples the app to the monorepo layout and bypasses the package boundary this workspace is supposed to consume. Import@shotlab/meticulous-clienthere instead, and keepapps/web/src/app.tsxon the same boundary.Proposed change
import { createMeticulousClient, type MeticulousClientOptions, -} from '../../../../packages/meticulous-client/src/index'; +} from '`@shotlab/meticulous-client`';🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/lib/create-dashboard-client.ts` around lines 1 - 4, The import in create-dashboard-client is reaching into the package source path instead of using the published package boundary. Update the createMeticulousClient and MeticulousClientOptions import to come from `@shotlab/meticulous-client`, and make the same boundary-safe import change in apps/web/src/app.tsx so both call sites consume the package entrypoint consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/app.test.tsx`:
- Line 74: The test is resolving mocks.deferreds.history and then exiting before
the final rerender settles, which can leave pending updates behind. Update the
relevant test in app.test.tsx to wait for the post-resolution UI state using the
empty-history assertion after mocks.deferreds.history.resolve, so the test only
finishes once the final render has completed.
In `@apps/web/src/app.tsx`:
- Around line 61-62: The “Last loaded profile” loading state in the
`getProfileCardValue`/switch handling is tied to both `loading.machine` and
`loading.lastProfile`, which turns off the skeleton too early when
`getMachine()` resolves before `getLastProfile()`. Update the loading condition
to depend on the profile request’s own settle state only, and keep the card in
loading mode until `getLastProfile()` finishes regardless of `loading.machine`.
In `@apps/web/src/lib/dashboard-selectors.ts`:
- Around line 55-56: The pre-heat card in dashboard-selectors is missing support
for the observed heat-on-boot payload key, so machines with that field fall back
to "Unknown". Update the `readBoolean` lookup in the pre-heat selector to
include `heat_on_boot` alongside the existing `preheat` and `pre_heat` keys,
keeping the `value` logic in the same selector so it resolves the actual
pre-heat state when present.
In `@apps/web/src/lib/dashboard-types.ts`:
- Around line 6-13: The `DashboardShotPoint` model currently makes `weight`
non-null, which forces missing shot samples to be fabricated as numbers instead
of being treated as gaps. Update the `DashboardShotPoint` interface to make
`weight` nullable, then adjust the selector/rendering flow in `shot-chart.ts`
and any consumers of `DashboardShotPoint.weight` so they pass through missing
values as null rather than coercing them to 0 or another placeholder.
---
Nitpick comments:
In `@apps/web/src/app.tsx`:
- Around line 88-194: The cleanup in the `useEffect` inside `App` only sets
`isCancelled`, so the `getMachine`, `getSettings`, `getHistory`, and
`getLastProfile` requests keep running after unmount or base URL changes. Add
request cancellation to the `createDashboardClient` flow and abort those
in-flight reads from the effect cleanup, while still keeping the existing
`isCancelled` guards around the state updates.
In `@apps/web/src/lib/create-dashboard-client.ts`:
- Around line 1-4: The import in create-dashboard-client is reaching into the
package source path instead of using the published package boundary. Update the
createMeticulousClient and MeticulousClientOptions import to come from
`@shotlab/meticulous-client`, and make the same boundary-safe import change in
apps/web/src/app.tsx so both call sites consume the package entrypoint
consistently.
In `@packages/meticulous-client/src/index.ts`:
- Line 73: The getCurrentHistory() contract is being widened back to a catch-all
JsonObject, which undoes the new history typing. Update the method in index.ts
to return Promise<HistoryEntry> if /history/current is always structured, or
introduce a separate explicit interface for any alternate payload instead of
using a union with JsonObject. Keep the change aligned with the existing
HistoryEntry type so callers get the intended specific history shape.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: caa44658-66a6-4ad7-ba4d-eb4ce0e0ac6d
⛔ Files ignored due to path filters (2)
apps/web/public/icon.svgis excluded by!**/*.svgyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (23)
apps/web/index.htmlapps/web/package.jsonapps/web/public/manifest.webmanifestapps/web/public/sw.jsapps/web/src/app.test.tsxapps/web/src/app.tsxapps/web/src/config.tsapps/web/src/lib/create-dashboard-client.test.tsapps/web/src/lib/create-dashboard-client.tsapps/web/src/lib/dashboard-selectors.test.tsapps/web/src/lib/dashboard-selectors.tsapps/web/src/lib/dashboard-types.tsapps/web/src/lib/load-dashboard-snapshot.test.tsapps/web/src/lib/load-dashboard-snapshot.tsapps/web/src/lib/shot-chart.test.tsapps/web/src/lib/shot-chart.tsapps/web/src/main.tsxapps/web/src/theme.tsapps/web/tsconfig.jsonapps/web/vite.config.tsdocs/plans/2026-06-28-web-dashboard-rest-shell.mdpackages/meticulous-client/src/index.test.tspackages/meticulous-client/src/index.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/meticulous-client/src/index.ts`:
- Around line 150-152: `MeticulousClient.getLastHistory()` is typed as returning
`HistoryEntry`, but the factory still uses
`get<HistoryResponse>('history/last')`, so update the `getLastHistory` mapping
in `MeticulousClient` to deserialize `history/last` as `HistoryEntry` instead of
`HistoryResponse`. Keep the change localized to the `getLastHistory` symbol so
the returned object matches the declared interface.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 5ecca02b-3fe7-4f49-9cde-97b03910fd87
📒 Files selected for processing (10)
apps/web/src/app.test.tsxapps/web/src/app.tsxapps/web/src/lib/create-dashboard-client.tsapps/web/src/lib/dashboard-selectors.test.tsapps/web/src/lib/dashboard-selectors.tsapps/web/src/lib/dashboard-types.tsapps/web/src/lib/load-dashboard-snapshot.tsapps/web/tsconfig.jsonpackages/meticulous-client/src/index.test.tspackages/meticulous-client/src/index.ts
✅ Files skipped from review due to trivial changes (1)
- apps/web/src/lib/dashboard-types.ts
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/web/src/lib/load-dashboard-snapshot.ts
- apps/web/tsconfig.json
- apps/web/src/lib/create-dashboard-client.ts
- apps/web/src/lib/dashboard-selectors.test.ts
- apps/web/src/app.test.tsx
- apps/web/src/app.tsx
- apps/web/src/lib/dashboard-selectors.ts
# Overview Add the first REST-only ShotLab web dashboard shell so the machine state and shot history can be explored in the browser before socket work and brew controls. ## Details - scaffold `@shotlab/web` with Vite, React, TypeScript, MUI, and `@mui/x-charts` - add direct browser-to-machine REST loading for machine, settings, last profile, and history - render live info cards, disabled safe-action placeholders, a shared shot chart surface, and a history browser - normalize observed history payloads into chart series for pressure, flow, gravimetric flow, and weight - move weight onto a secondary chart axis so the primary axis stays readable for the flow-range metrics - update `@shotlab/meticulous-client` history typing to match the verified payload shape ## Related Tickets and/or Pull Requests - Relates to the roadmap step for the first web dashboard shell ## Checklist - [x] Tests added or updated - [ ] README and TSDoc updated if the public API changed - [ ] Breaking changes called out (if any) - [ ] Roadmap item checked off if this PR completes one <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced a new Web Dashboard experience with live status cards, interactive charts, selected shot details, and history browsing. * Added web app metadata (manifest) and a service worker for improved offline/launch behavior. * Added shared theme and a React/MUI app entry setup. * **Bug Fixes** * Improved progressive loading and clearer error/warning display when dashboard data can’t be retrieved. * Added stronger handling for missing/partial machine, profile, and history data to avoid blank/incorrect UI. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Overview
Add the first REST-only ShotLab web dashboard shell so the machine state and shot history can be explored in the browser before socket work and brew controls.
Details
@shotlab/webwith Vite, React, TypeScript, MUI, and@mui/x-charts@shotlab/meticulous-clienthistory typing to match the verified payload shapeRelated Tickets and/or Pull Requests
Checklist
Summary by CodeRabbit