feat(example-apps): add dashrate#98
Conversation
DashRate is a React + TypeScript + Vite app demonstrating Platform v4 document aggregation features (count, sum, average) and document history for rating tutorial resources on testnet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restructure the resource rating summary into a single flowing block (stars + average out of 5, then review count and total points as muted detail), reorder recent-review cards to lead with the platform identity and drop the redundant resource title, clarify sidebar review counts with a pluralized noun, and soften the review form copy and textarea height. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point DEFAULT_CONTRACT_ID at a published testnet DashRate contract so fresh installs read aggregates and reviews immediately instead of an empty state, and update the README to document the default and the localStorage override. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace whole-star rounding with a StarMeter component that clips the gold fill to the exact average, so aggregate ratings render partial stars in the sidebar and detail header. Group the rating, review form, and recent reviews as divider-separated sections of one resource instead of bordered boxes, and render reviews and history as continuous divided lists rather than stacked cards. Move the aggregate rating under the title, put Open on the title row (opening in a new tab), and place the refreshing indicator on the eyebrow line with a reserved height so toggling it no longer shifts the layout. Restyle the signed-out prompt as a sign-in CTA that links to Settings, and soften the resource card hover so it no longer floods the card. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a per-star distribution histogram beside the aggregate rating and a server-side rating filter on the reviews list, showcasing Platform 4.0 grouped and range counts. The distribution comes from one grouped count (`count` GROUP BY `rating` over a `[resourceId, rating]` countable + rangeCountable index); the average is derived in JS from the per-star counts, so no sum/average query is needed. The reviews filter adds a `rating == N` clause served by the same index, with its `orderBy` aligned to the index's trailing property. A plain `count` over `[resourceId]` supplies the total. Both indices are count-only on purpose: pairing `summable` on the `[resourceId]` prefix with the count-only `[resourceId, rating]` continuation registers fine but breaks every document insert (dashpay/platform#3960), so the average moved off `summable` and onto the derived distribution. Add a dashrate CLAUDE.md documenting the query patterns and the index gotchas (grouped-count key encoding, rangeCountable, the summable-prefix conflict, orderBy-vs-index). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve each on-screen identity's DPNS name and display it in place of the short identity ID — in the recent-reviews rows, the My reviews header, and the Settings identity line — falling back to the short ID when no name is registered. Names resolve lazily after the lists render: only distinct, not-yet-cached owners are looked up, in parallel, and cached by identity across resource switches, so a feed of many rows by few reviewers costs one lookup per reviewer and revisiting a resource costs nothing. Make the dedicated reviews effect the single owner of the recent-reviews list, keyed on resource and rating filter, so clearing the filter re-fetches the full list instead of leaving the filtered subset on screen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switching resources or rating filters left the previous selection's reviews on screen until the slower document query returned. Reset the review list during render when the (resource, filter) key changes, so the section goes empty immediately and repopulates when the fetch lands. Replace the misleading "No reviews yet" shown during that gap with a "Loading reviews…" indicator (relocated from the header eyebrow row), so an in-flight load no longer reads as an empty resource. Drop the default top margin on section headings so "Your review" and "Review history" align with "Recent reviews" instead of sitting lower. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tests for the previously untested write path and pure helpers, and fill the read-path gaps: review create/update branches and rating validation, format helpers, DPNS name resolution, catalog integrity, the remaining query helpers (getRatingCount, listMyReviews, findMyReviewForResource), normalizeReviews shape tolerance, and the review-history limit clamp. Add a test:coverage script backed by @vitest/coverage-v8 and a coverage block in the Vite config, matching the sibling apps. Ignore the generated coverage/ output in the ESLint config. Wire findResource into App.tsx in place of the two inline RESOURCES.find lookups so the exported helper is real app behavior rather than dead code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Dash bridge link so users without an identity have a path to create one for testing. Move the identity index and contract controls behind an Advanced settings disclosure so the default sign-in view is just the mnemonic. Group them in a single bordered panel, render the index as a compact numeric field with a help note, and label the contract ID optional. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-fetch the current resource's review list after a successful save and swap it in place, so an edited or new review appears under Recent reviews without navigating away or refreshing. Swapping in place (no clear) keeps the existing rows visible, avoiding a flash to the loading state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a workflow that runs the Vitest suite and build (tsc -b included) on push/PR touching example-apps/dashrate, matching how the other apps are gated. Also apply Prettier to the test files so they match the project style. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Break the monolithic App.tsx into focused view components, data hooks, and shared session/ratings modules to reduce its size and improve maintainability. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the resource summary directly under its title, drop the redundant rating prompt and "Comment" label in favor of an accessible placeholder plus a visually hidden label, and turn revision history into a "Show/Hide previous versions" toggle nested under the user's review instead of a peer section. Add focus styling and a subtle background for form fields, tighten the spacing between the stars and the comment box, and remove the dead .section-head selector and an obsolete .settings-form comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the redundant per-operation start/success logs from the read-side queries — the per-resource fan-out emitted ~28 console lines per Resources-view load. Keep the error logs, replace the per-resource success spam with one aggregate "Loaded ratings for N resources." line, and keep one summary line on the review-list and my-reviews loads. Remove the now-unused log parameter from findMyReviewForResource (its result already flows into UI state) and the dead distributionLabel helper. Add a 480px small-phone CSS tier with tighter spacing and a few row→column stacks below the existing 820px breakpoint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mnemonic input is a textarea, so Enter inserted a newline instead of submitting the login form. Submit on Enter (without Shift) when a mnemonic is present and the form isn't busy; Shift+Enter still adds a newline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…yout Describe the current App-as-orchestrator structure with the components/, hooks/, session/, and expanded lib/ directories, and document the sdkCore.ts loader, the full test list, and the test:coverage script in both CLAUDE.md and the README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On the stacked mobile layout the resource list sits above the detail panel, so tapping a resource left the rating and reviews off-screen. Selecting now scrolls the detail into view at the ≤820px breakpoint; the desktop two-column layout is untouched. Pin the topbar (sticky, top: 0) on mobile so the nav tabs stay reachable after the jump, relax the shell's overflow to horizontal-only so sticky isn't trapped, and offset the detail's scroll-margin-top so the heading clears the pinned header. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reveal the histogram count on row hover/focus as an "N review(s)" label, and hide the gold bar entirely at zero votes instead of leaving a 2px sliver. Flatten the unselected resource cards — transparent fill and border, no shadow, tighter list gap — so only the selected card carries the green tint and outline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stogram Measure the sticky topbar's real height when scrolling to the detail panel on mobile, instead of a hardcoded 120px offset that over- or undershoots once the header wraps to a taller stack. Gate the histogram count's hover reveal behind a real hovering pointer so a tap or scroll over a row on touch devices no longer leaves the count stuck visible; touch keeps the active/focus reveals. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Matches the in-app GitHub link the sibling example apps already carry, so the deployed dashrate app links back to the canonical platform-tutorials repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Testing Library component/hook tests for the view shells, review pieces, and SDK-backed hooks, mocking the SDK loaders so the bundle never enters jsdom. Extend the Vitest include to `.tsx` and have tsconfig.app strict-typecheck the test files. Add a Playwright e2e suite (smoke + settings) running desktop and mobile against real testnet, with playwright.config auto-booting Vite on :5182, plus the test:e2e scripts, dev deps, and lint/tsconfig excludes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Vitest coverage for App.tsx orchestration handlers (save-review guards and success refresh, register/clear/submit contract, sign-out, load history) and for the SDK/WASM error shapes errorMessage extracts. Also list dashrate in the example-apps README and ignore Playwright report and test-results output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds the DashRate example app, its Dash SDK data and mutation helpers, React hooks and views, app-level orchestration, CI/tooling configuration, and unit/e2e coverage. ChangesDashRate app rollout
Sequence Diagram(s)sequenceDiagram
participant App
participant saveReview
participant findMyReviewForResource
participant DashSdk
App->>saveReview: session, contractId, resourceId, rating, reviewText
saveReview->>findMyReviewForResource: ownerId + resourceId
findMyReviewForResource->>DashSdk: sdk.documents.query(...)
DashSdk-->>findMyReviewForResource: existing review or none
saveReview->>DashSdk: sdk.documents.create / replace
DashSdk-->>saveReview: review id
saveReview-->>App: review id
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
example-apps/dashrate/eslint.config.jsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. example-apps/dashrate/playwright.config.tsESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox. example-apps/dashrate/src/App.tsxESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.
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: 10
🧹 Nitpick comments (19)
example-apps/dashrate/src/hooks/useResourceRatings.ts (1)
138-160: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff
loadResourceDatare-fetches every resource's count/distribution on each resource selection.
selectedResourceIdis inloadResourceData's dependency list (Line 157) only because of the per-resourcefindMyReviewForResourceblock (Lines 138-150). SinceloadResourceDatais a dependency of the effect at Lines 197-217, changing the selected resource recreates the callback and reruns the effect, re-issuinggetRatingCount+getRatingDistributionfor allRESOURCESeven though those aggregates don't depend on the selection. Consider splitting the per-resource "my review" lookup into its own effect/callback keyed onselectedResourceId, leaving the all-resource aggregate load keyed oncontractId/session. If the full reload is intentional for the demo, please disregard.Also applies to: 197-217
🤖 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 `@example-apps/dashrate/src/hooks/useResourceRatings.ts` around lines 138 - 160, Move the selected-resource “my review” lookup out of loadResourceData so changing selectedResourceId does not recreate that callback and rerun the aggregate refresh effect; keep the RESOURCES count/distribution loading in loadResourceData keyed only by contractId/session, and add a separate effect or callback for findMyReviewForResource, setMySelectedReview, setRating, setHoverRating, and setReviewText that depends on selectedResourceId and session. Update the useEffect that currently depends on loadResourceData to avoid re-fetching all resource aggregates when only the selection changes..github/workflows/dashrate-ci.yml (1)
32-32: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valueConsider hardening the checkout with
persist-credentials: false.zizmor flags credential persistence (artipacked). Risk here is low (
contents: read, no pushes), but since no step needs the token, disabling persistence is a cheap hardening.🔒 Proposed change
- - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false🤖 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 @.github/workflows/dashrate-ci.yml at line 32, The checkout step in the dashrate CI workflow is persisting Git credentials unnecessarily, so harden the existing actions/checkout usage by disabling credential persistence. Update the checkout configuration to set persist-credentials to false since no later step needs the token, keeping the workflow behavior unchanged while reducing exposure.Source: Linters/SAST tools
example-apps/dashrate/src/dash/contract.ts (1)
84-90: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winGuard
localStoragewrites like the read path.
loadStoredContractIdalready wrapsgetItemin try/catch, butsaveContractId/clearStoredContractIdcallsetItem/removeItemunguarded. These throw when storage is disabled or full (e.g. Safari private mode). Notably,saveContractIdruns at Line 143 aftersdk.contracts.publishsucceeds, so a storage failure would surface as an error even though the contract was already published on-chain, losing the returned ID.♻️ Proposed guard
export function saveContractId(contractId: string): void { - localStorage.setItem(STORAGE_KEY, contractId); + try { + localStorage.setItem(STORAGE_KEY, contractId); + } catch { + // ignore storage failures (e.g. private mode / quota) + } } export function clearStoredContractId(): void { - localStorage.removeItem(STORAGE_KEY); + try { + localStorage.removeItem(STORAGE_KEY); + } catch { + // ignore storage failures + } }🤖 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 `@example-apps/dashrate/src/dash/contract.ts` around lines 84 - 90, The localStorage write path in saveContractId and clearStoredContractId is unguarded, unlike loadStoredContractId, so wrap both setItem and removeItem in the same try/catch style used by the read helper. Update the contract.ts storage helpers to swallow or safely handle storage errors, and ensure the saveContractId call site after sdk.contracts.publish does not turn a successful publish into a failure because persistence to localStorage was unavailable.example-apps/dashrate/test/ReviewRow.test.tsx (1)
1-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This test file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/ReviewRow.test.tsx` around lines 1 - 45, This test file is not formatted according to the repository’s Prettier rules. Reformat the ReviewRow test to match the app’s standard style in the same file, keeping the existing assertions and structure intact while converting the current double-quoted imports/strings and spacing to the project’s Prettier output for this `ReviewRow` test.Source: Coding guidelines
example-apps/dashrate/src/catalog/resources.ts (1)
1-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This file uses double-quoted strings throughout, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/catalog/resources.ts` around lines 1 - 64, The RESOURCES module and findResource function need to be reformatted to match the app’s Prettier contract. Update the RatedResource interface, RESOURCES array, and findResource implementation in this file to use the repository’s standard formatting (single quotes, 2-space indentation, and trailing commas where applicable) so it is consistent with the rest of the codebase.Source: Coding guidelines
example-apps/dashrate/test/MyReviewCard.test.tsx (1)
1-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This test file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/MyReviewCard.test.tsx` around lines 1 - 56, This test file needs to be reformatted to match the repository Prettier contract. Update the Jest/Vitest test in MyReviewCard.test.tsx so imports, strings, and other formatting follow the app’s Prettier rules (single quotes, 2-space indentation, trailing commas) while keeping the existing test logic and symbols like makeReview, MyReviewCard, and vi.fn unchanged.Source: Coding guidelines
example-apps/dashrate/test/MyReviewsView.test.tsx (1)
1-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This test file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/MyReviewsView.test.tsx` around lines 1 - 110, The test file formatting does not match the repository’s Prettier contract, so update the MyReviewsView test to follow the app’s configured style. Reformat the existing imports, strings, indentation, and trailing commas in MyReviewsView.test.tsx to match Prettier output, keeping the current test behavior unchanged.Source: Coding guidelines
example-apps/dashrate/src/components/HowItWorks.tsx (1)
1-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/HowItWorks.tsx` around lines 1 - 39, Format the HowItWorks component to match the repository’s Prettier contract: update the JSX in HowItWorks so string literals and attributes follow the project’s single-quote style, 2-space indentation, and trailing-comma rules. Keep the component behavior unchanged and use the existing HowItWorks export as the target for the formatting pass.Source: Coding guidelines
example-apps/dashrate/src/components/AppNotices.tsx (1)
1-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/AppNotices.tsx` around lines 1 - 19, Run the AppNotices component through the project’s Prettier formatting so it matches the repository contract; the current JSX in AppNotices uses double quotes and should be reformatted to the standard single-quote, 2-space indentation, and trailing-comma style. Keep the component behavior unchanged and use the existing AppNotices export as the target for the formatting-only update.Source: Coding guidelines
example-apps/dashrate/test/AppNotices.test.tsx (1)
1-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This test file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/AppNotices.test.tsx` around lines 1 - 41, Format the AppNotices test file with the repository’s Prettier rules: convert the existing double-quoted imports and test strings to single quotes, keep 2-space indentation, and preserve/add trailing commas where Prettier would. Use the AppNotices test cases and the afterEach/render/describe blocks as the targets for the formatting pass.Source: Coding guidelines
example-apps/dashrate/test/RecentReviews.test.tsx (1)
1-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun this file through the app's Prettier config.
This test file uses double-quoted strings, so it won't match the repository formatting contract. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/RecentReviews.test.tsx` around lines 1 - 98, The RecentReviews test file is not matching the repository’s Prettier style, mainly due to quote and formatting inconsistencies. Reformat the test to the app’s standard Prettier output so imports, strings, and indentation are consistent with the rest of the codebase. Keep the changes confined to the RecentReviews test helpers and test cases, and preserve the existing behavior while normalizing the formatting.Source: Coding guidelines
example-apps/dashrate/test/TopNav.test.tsx (1)
1-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX test still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/TopNav.test.tsx` around lines 1 - 54, This TopNav test file is not matching the app’s Prettier style, so reformat the TSX in TopNav.test.tsx using the project’s formatter. Update the imports, string literals, and trailing commas to the single-quote Prettier conventions used across the repo, while keeping the existing TopNav, NAV, and vi-based test logic unchanged.Source: Coding guidelines
example-apps/dashrate/src/components/RecentReviews.tsx (1)
1-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX file still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/RecentReviews.tsx` around lines 1 - 60, RecentReviews still isn’t formatted with the app’s Prettier rules, specifically the import and string quoting style. Reformat the RecentReviews component in example-apps/dashrate/src/components/RecentReviews.tsx using the project Prettier config so the imports and all string literals follow single-quote conventions, with the existing 2-space indentation and trailing commas preserved.Source: Coding guidelines
example-apps/dashrate/src/components/ResourcesView.tsx (1)
1-231: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX file still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/ResourcesView.tsx` around lines 1 - 231, The ResourcesView TSX file is not formatted according to the app’s Prettier rules, so update it to match the configured style. Reformat the imports and string literals in ResourcesView and its helper logic using the Prettier config (single quotes, 2-space indentation, trailing commas) while preserving behavior and keeping the existing symbols like ResourcesView and handleSelectResource intact.Source: Coding guidelines
example-apps/dashrate/src/components/ReviewForm.tsx (1)
1-117: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX file still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/ReviewForm.tsx` around lines 1 - 117, The ReviewForm TSX file is not aligned with the app’s Prettier formatting rules, specifically the quote style and any related formatting conventions. Run ReviewForm through the project’s Prettier config and ensure the exported ReviewForm component, its import statements, and all JSX/string literals are formatted consistently with single quotes, 2-space indentation, and trailing commas where applicable.Source: Coding guidelines
example-apps/dashrate/src/components/ReviewHistory.tsx (1)
1-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX file still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/ReviewHistory.tsx` around lines 1 - 31, The ReviewHistory component needs formatting to match the app’s Prettier rules, since it still uses double quotes and may not fully conform to the required style. Run the ReviewHistory TSX through the project’s Prettier config so the imports, strings, indentation, and trailing commas are normalized consistently with the existing formatting standards.Source: Coding guidelines
example-apps/dashrate/src/components/StarMeter.tsx (1)
1-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX file still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/src/components/StarMeter.tsx` around lines 1 - 31, The StarMeter component in StarMeter.tsx is not formatted according to the app’s Prettier rules, so update the file to match the existing formatting conventions used in the codebase. Run it through the project’s Prettier config and ensure the `StarMeter` import, string literals, indentation, and any trailing commas follow the required single-quote, 2-space, trailing-comma style.Source: Coding guidelines
example-apps/dashrate/test/ReviewHistory.test.tsx (1)
1-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX test still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/ReviewHistory.test.tsx` around lines 1 - 38, The ReviewHistory test file is not formatted according to the app’s Prettier rules, specifically the imports and string literals still use double quotes. Reformat the test to match the existing Prettier config and project style, keeping the same behavior in ReviewHistory and the entries test data while ensuring single-quote usage, 2-space indentation, and trailing commas where applicable.Source: Coding guidelines
example-apps/dashrate/test/StarMeter.test.tsx (1)
1-55: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRun the file through the app’s Prettier config.
This TSX test still uses double-quoted imports/strings instead of the required single-quote style. As per coding guidelines,
**/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.🤖 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 `@example-apps/dashrate/test/StarMeter.test.tsx` around lines 1 - 55, The StarMeter test file needs to be formatted to match the app’s Prettier rules, since it still uses double quotes instead of the required single-quote style. Reformat the existing `StarMeter.test.tsx` content with Prettier so imports, strings, indentation, and trailing commas conform to the project’s standard, keeping the same test names and helpers such as `fill` and `describe("StarMeter", ...)`.Source: Coding guidelines
🤖 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 `@example-apps/dashrate/.prettierrc.json`:
- Around line 1-4: The app-local Prettier config is missing the single-quote
setting, so formatting in this workspace still emits double-quoted JS/TS output.
Update the Prettier configuration in the dashrate app’s .prettierrc.json to
enable single quotes alongside the existing printWidth and trailingComma
settings, so npm run format follows the repo’s formatting contract.
In `@example-apps/dashrate/eslint.config.js`:
- Around line 11-15: The flat ESLint config block for `files: ["**/*.{ts,tsx}"]`
is too broad and applies browser globals to `playwright.config.ts`, causing
Node-only references like `process.env.CI` to fail linting. Update the config in
`eslint.config.js` by either narrowing this browser-scoped block to only
app/test source files or adding a separate Node-scoped override for
`playwright.config.ts`, keeping the browser globals tied to the correct sources
and using the existing flat-config structure.
In `@example-apps/dashrate/README.md`:
- Around line 50-56: The README description of aggregate queries is inconsistent
about where the total review count comes from; update the wording in the
dashrate README to make the query plan consistent. Use the existing
aggregate/index terms already mentioned there (`resourceId`, `rating`,
`countable`, `rangeCountable`, `summable`) and clarify whether the standalone
count index is only for total counts or whether the grouped count query is the
single source for histogram, sum, and average so the reader sees one coherent
explanation.
In `@example-apps/dashrate/src/components/AppNotices.tsx`:
- Around line 12-15: Update the notice in AppNotices so it no longer says “No
default contract is bundled yet,” since DashRate now ships a default testnet
contract ID. Reword the message to describe a missing or cleared active contract
configuration instead, while keeping the guidance about signing in, registering
a contract, or pasting an existing contract ID in Settings. Use the notice
markup in AppNotices as the target for the text change.
- Line 10: The status message in AppNotices is rendered as a plain paragraph, so
assistive tech may not announce updates. Update the status rendering in
AppNotices to use an accessible live region, such as adding role="status" or an
aria-live attribute to the existing status element, so changes are announced
when status updates at runtime.
In `@example-apps/dashrate/src/components/ReviewForm.tsx`:
- Around line 36-37: The history toggle logic in ReviewForm is load-only right
now, but the UI label and state imply a real open/close interaction. Update the
ReviewForm prop contract and toggle handling so the control has an explicit
expanded/collapse state or clearly remains load-only, and make the button
behavior match the displayed label instead of always calling onLoadHistory. Use
the existing ReviewForm component and the historyOpen/displayRating logic as the
place to wire in the new state or callback.
In `@example-apps/dashrate/src/components/StarMeter.tsx`:
- Around line 10-12: The spoken label in StarMeter is using the raw rating
instead of the same clamped value used for fillPercent, so update the label
logic to reuse the bounded 0–5 value for both the visual meter and the
aria-label. Fix this in StarMeter by deriving a single clamped rating from value
and using it for both the percentage fill and the accessible text, while still
keeping the null case as the “No rating yet” label.
In `@example-apps/dashrate/src/dash/resolveDpnsName.ts`:
- Around line 16-21: The resolveDpnsName helper currently returns null for both
a real “no DPNS name” result and for SDK lookup failures, which causes
useDpnsNames to cache transient errors as permanent misses. Update
resolveDpnsName to distinguish a successful empty result from an exception
thrown by sdk.dpns.username, and return or surface failures in a separate way so
useDpnsNames can retry rather than caching null; keep the existing normalization
logic in resolveDpnsName for valid string results.
In `@example-apps/dashrate/src/styles.css`:
- Around line 263-266: The .sr-only accessibility helper still uses the
deprecated clip property, which Stylelint flags. Update the .sr-only rule in the
stylesheet to remove clip and keep the existing clip-path-based visually hidden
behavior, preserving the rest of the rules unchanged.
In `@example-apps/dashrate/test/SettingsView.test.tsx`:
- Around line 114-116: The test assertion around the rendered current value is
too generic and can break once the contract ID is displayed inside the same
paragraph. Update the expectation in SettingsView.test.tsx to target the full
rendered text for the “Current:” label together with the contract ID, using the
existing screen query near the clear-button interaction so the assertion matches
the actual SettingsView output.
---
Nitpick comments:
In @.github/workflows/dashrate-ci.yml:
- Line 32: The checkout step in the dashrate CI workflow is persisting Git
credentials unnecessarily, so harden the existing actions/checkout usage by
disabling credential persistence. Update the checkout configuration to set
persist-credentials to false since no later step needs the token, keeping the
workflow behavior unchanged while reducing exposure.
In `@example-apps/dashrate/src/catalog/resources.ts`:
- Around line 1-64: The RESOURCES module and findResource function need to be
reformatted to match the app’s Prettier contract. Update the RatedResource
interface, RESOURCES array, and findResource implementation in this file to use
the repository’s standard formatting (single quotes, 2-space indentation, and
trailing commas where applicable) so it is consistent with the rest of the
codebase.
In `@example-apps/dashrate/src/components/AppNotices.tsx`:
- Around line 1-19: Run the AppNotices component through the project’s Prettier
formatting so it matches the repository contract; the current JSX in AppNotices
uses double quotes and should be reformatted to the standard single-quote,
2-space indentation, and trailing-comma style. Keep the component behavior
unchanged and use the existing AppNotices export as the target for the
formatting-only update.
In `@example-apps/dashrate/src/components/HowItWorks.tsx`:
- Around line 1-39: Format the HowItWorks component to match the repository’s
Prettier contract: update the JSX in HowItWorks so string literals and
attributes follow the project’s single-quote style, 2-space indentation, and
trailing-comma rules. Keep the component behavior unchanged and use the existing
HowItWorks export as the target for the formatting pass.
In `@example-apps/dashrate/src/components/RecentReviews.tsx`:
- Around line 1-60: RecentReviews still isn’t formatted with the app’s Prettier
rules, specifically the import and string quoting style. Reformat the
RecentReviews component in
example-apps/dashrate/src/components/RecentReviews.tsx using the project
Prettier config so the imports and all string literals follow single-quote
conventions, with the existing 2-space indentation and trailing commas
preserved.
In `@example-apps/dashrate/src/components/ResourcesView.tsx`:
- Around line 1-231: The ResourcesView TSX file is not formatted according to
the app’s Prettier rules, so update it to match the configured style. Reformat
the imports and string literals in ResourcesView and its helper logic using the
Prettier config (single quotes, 2-space indentation, trailing commas) while
preserving behavior and keeping the existing symbols like ResourcesView and
handleSelectResource intact.
In `@example-apps/dashrate/src/components/ReviewForm.tsx`:
- Around line 1-117: The ReviewForm TSX file is not aligned with the app’s
Prettier formatting rules, specifically the quote style and any related
formatting conventions. Run ReviewForm through the project’s Prettier config and
ensure the exported ReviewForm component, its import statements, and all
JSX/string literals are formatted consistently with single quotes, 2-space
indentation, and trailing commas where applicable.
In `@example-apps/dashrate/src/components/ReviewHistory.tsx`:
- Around line 1-31: The ReviewHistory component needs formatting to match the
app’s Prettier rules, since it still uses double quotes and may not fully
conform to the required style. Run the ReviewHistory TSX through the project’s
Prettier config so the imports, strings, indentation, and trailing commas are
normalized consistently with the existing formatting standards.
In `@example-apps/dashrate/src/components/StarMeter.tsx`:
- Around line 1-31: The StarMeter component in StarMeter.tsx is not formatted
according to the app’s Prettier rules, so update the file to match the existing
formatting conventions used in the codebase. Run it through the project’s
Prettier config and ensure the `StarMeter` import, string literals, indentation,
and any trailing commas follow the required single-quote, 2-space,
trailing-comma style.
In `@example-apps/dashrate/src/dash/contract.ts`:
- Around line 84-90: The localStorage write path in saveContractId and
clearStoredContractId is unguarded, unlike loadStoredContractId, so wrap both
setItem and removeItem in the same try/catch style used by the read helper.
Update the contract.ts storage helpers to swallow or safely handle storage
errors, and ensure the saveContractId call site after sdk.contracts.publish does
not turn a successful publish into a failure because persistence to localStorage
was unavailable.
In `@example-apps/dashrate/src/hooks/useResourceRatings.ts`:
- Around line 138-160: Move the selected-resource “my review” lookup out of
loadResourceData so changing selectedResourceId does not recreate that callback
and rerun the aggregate refresh effect; keep the RESOURCES count/distribution
loading in loadResourceData keyed only by contractId/session, and add a separate
effect or callback for findMyReviewForResource, setMySelectedReview, setRating,
setHoverRating, and setReviewText that depends on selectedResourceId and
session. Update the useEffect that currently depends on loadResourceData to
avoid re-fetching all resource aggregates when only the selection changes.
In `@example-apps/dashrate/test/AppNotices.test.tsx`:
- Around line 1-41: Format the AppNotices test file with the repository’s
Prettier rules: convert the existing double-quoted imports and test strings to
single quotes, keep 2-space indentation, and preserve/add trailing commas where
Prettier would. Use the AppNotices test cases and the afterEach/render/describe
blocks as the targets for the formatting pass.
In `@example-apps/dashrate/test/MyReviewCard.test.tsx`:
- Around line 1-56: This test file needs to be reformatted to match the
repository Prettier contract. Update the Jest/Vitest test in
MyReviewCard.test.tsx so imports, strings, and other formatting follow the app’s
Prettier rules (single quotes, 2-space indentation, trailing commas) while
keeping the existing test logic and symbols like makeReview, MyReviewCard, and
vi.fn unchanged.
In `@example-apps/dashrate/test/MyReviewsView.test.tsx`:
- Around line 1-110: The test file formatting does not match the repository’s
Prettier contract, so update the MyReviewsView test to follow the app’s
configured style. Reformat the existing imports, strings, indentation, and
trailing commas in MyReviewsView.test.tsx to match Prettier output, keeping the
current test behavior unchanged.
In `@example-apps/dashrate/test/RecentReviews.test.tsx`:
- Around line 1-98: The RecentReviews test file is not matching the repository’s
Prettier style, mainly due to quote and formatting inconsistencies. Reformat the
test to the app’s standard Prettier output so imports, strings, and indentation
are consistent with the rest of the codebase. Keep the changes confined to the
RecentReviews test helpers and test cases, and preserve the existing behavior
while normalizing the formatting.
In `@example-apps/dashrate/test/ReviewHistory.test.tsx`:
- Around line 1-38: The ReviewHistory test file is not formatted according to
the app’s Prettier rules, specifically the imports and string literals still use
double quotes. Reformat the test to match the existing Prettier config and
project style, keeping the same behavior in ReviewHistory and the entries test
data while ensuring single-quote usage, 2-space indentation, and trailing commas
where applicable.
In `@example-apps/dashrate/test/ReviewRow.test.tsx`:
- Around line 1-45: This test file is not formatted according to the
repository’s Prettier rules. Reformat the ReviewRow test to match the app’s
standard style in the same file, keeping the existing assertions and structure
intact while converting the current double-quoted imports/strings and spacing to
the project’s Prettier output for this `ReviewRow` test.
In `@example-apps/dashrate/test/StarMeter.test.tsx`:
- Around line 1-55: The StarMeter test file needs to be formatted to match the
app’s Prettier rules, since it still uses double quotes instead of the required
single-quote style. Reformat the existing `StarMeter.test.tsx` content with
Prettier so imports, strings, indentation, and trailing commas conform to the
project’s standard, keeping the same test names and helpers such as `fill` and
`describe("StarMeter", ...)`.
In `@example-apps/dashrate/test/TopNav.test.tsx`:
- Around line 1-54: This TopNav test file is not matching the app’s Prettier
style, so reformat the TSX in TopNav.test.tsx using the project’s formatter.
Update the imports, string literals, and trailing commas to the single-quote
Prettier conventions used across the repo, while keeping the existing TopNav,
NAV, and vi-based test logic unchanged.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: a4cd5598-adca-46bf-b18b-bdd88558fede
⛔ Files ignored due to path filters (1)
example-apps/dashrate/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (75)
.github/workflows/dashrate-ci.yml.gitignoreexample-apps/README.mdexample-apps/dashrate/.prettierignoreexample-apps/dashrate/.prettierrc.jsonexample-apps/dashrate/CLAUDE.mdexample-apps/dashrate/README.mdexample-apps/dashrate/eslint.config.jsexample-apps/dashrate/index.htmlexample-apps/dashrate/package.jsonexample-apps/dashrate/playwright.config.tsexample-apps/dashrate/src/App.tsxexample-apps/dashrate/src/catalog/resources.tsexample-apps/dashrate/src/components/AppNotices.tsxexample-apps/dashrate/src/components/HowItWorks.tsxexample-apps/dashrate/src/components/MyReviewCard.tsxexample-apps/dashrate/src/components/MyReviewsView.tsxexample-apps/dashrate/src/components/RecentReviews.tsxexample-apps/dashrate/src/components/ResourcesView.tsxexample-apps/dashrate/src/components/ReviewForm.tsxexample-apps/dashrate/src/components/ReviewHistory.tsxexample-apps/dashrate/src/components/ReviewRow.tsxexample-apps/dashrate/src/components/SettingsView.tsxexample-apps/dashrate/src/components/StarMeter.tsxexample-apps/dashrate/src/components/TopNav.tsxexample-apps/dashrate/src/dash/client.tsexample-apps/dashrate/src/dash/contract.tsexample-apps/dashrate/src/dash/history.tsexample-apps/dashrate/src/dash/keyManager.tsexample-apps/dashrate/src/dash/queries.tsexample-apps/dashrate/src/dash/resolveDpnsName.tsexample-apps/dashrate/src/dash/review.tsexample-apps/dashrate/src/dash/sdkCore.tsexample-apps/dashrate/src/dash/sdkModule.tsexample-apps/dashrate/src/dash/types.tsexample-apps/dashrate/src/hooks/useDpnsNames.tsexample-apps/dashrate/src/hooks/useMyReviews.tsexample-apps/dashrate/src/hooks/useResourceRatings.tsexample-apps/dashrate/src/lib/format.tsexample-apps/dashrate/src/lib/logger.tsexample-apps/dashrate/src/lib/ratings.tsexample-apps/dashrate/src/main.tsxexample-apps/dashrate/src/session/types.tsexample-apps/dashrate/src/styles.cssexample-apps/dashrate/src/vite-env.d.tsexample-apps/dashrate/test/App.test.tsxexample-apps/dashrate/test/AppNotices.test.tsxexample-apps/dashrate/test/MyReviewCard.test.tsxexample-apps/dashrate/test/MyReviewsView.test.tsxexample-apps/dashrate/test/RecentReviews.test.tsxexample-apps/dashrate/test/ResourcesView.test.tsxexample-apps/dashrate/test/ReviewForm.test.tsxexample-apps/dashrate/test/ReviewHistory.test.tsxexample-apps/dashrate/test/ReviewRow.test.tsxexample-apps/dashrate/test/SettingsView.test.tsxexample-apps/dashrate/test/StarMeter.test.tsxexample-apps/dashrate/test/TopNav.test.tsxexample-apps/dashrate/test/contract.test.tsexample-apps/dashrate/test/e2e/fixtures.tsexample-apps/dashrate/test/e2e/settings.spec.tsexample-apps/dashrate/test/e2e/smoke.spec.tsexample-apps/dashrate/test/format.test.tsexample-apps/dashrate/test/history.test.tsexample-apps/dashrate/test/logger.test.tsexample-apps/dashrate/test/queries.test.tsexample-apps/dashrate/test/resolveDpnsName.test.tsexample-apps/dashrate/test/resources.test.tsexample-apps/dashrate/test/review.test.tsexample-apps/dashrate/test/useDpnsNames.test.tsxexample-apps/dashrate/test/useMyReviews.test.tsxexample-apps/dashrate/test/useResourceRatings.test.tsxexample-apps/dashrate/tsconfig.app.jsonexample-apps/dashrate/tsconfig.jsonexample-apps/dashrate/tsconfig.node.jsonexample-apps/dashrate/vite.config.ts
| { | ||
| "printWidth": 80, | ||
| "trailingComma": "all" | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Enable single quotes in the app-local Prettier config.
npm run format in this workspace will currently keep emitting double-quoted JS/TS output, which breaks the repo formatting contract for example-apps/dashrate.
♻️ Proposed fix
{
"printWidth": 80,
+ "singleQuote": true,
"trailingComma": "all"
}As per coding guidelines, **/*.{js,mjs,ts,tsx,json}: Prettier formatting must use single quotes, 2-space indentation, and trailing commas.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| { | |
| "printWidth": 80, | |
| "trailingComma": "all" | |
| } | |
| { | |
| "printWidth": 80, | |
| "singleQuote": true, | |
| "trailingComma": "all" | |
| } |
🤖 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 `@example-apps/dashrate/.prettierrc.json` around lines 1 - 4, The app-local
Prettier config is missing the single-quote setting, so formatting in this
workspace still emits double-quoted JS/TS output. Update the Prettier
configuration in the dashrate app’s .prettierrc.json to enable single quotes
alongside the existing printWidth and trailingComma settings, so npm run format
follows the repo’s formatting contract.
Source: Coding guidelines
| files: ["**/*.{ts,tsx}"], | ||
| languageOptions: { | ||
| ecmaVersion: 2022, | ||
| globals: globals.browser, | ||
| }, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Split browser and Node globals in the flat config.
files: ['**/*.{ts,tsx}'] also matches playwright.config.ts, but this block only exposes browser globals. That makes process.env.CI in example-apps/dashrate/playwright.config.ts a lint error unless you add a Node-scoped override or narrow this browser block to app/test sources.
♻️ Proposed fix
export default tseslint.config(
{ ignores: ['dist', 'coverage', 'playwright-report', 'test-results'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
- files: ['**/*.{ts,tsx}'],
+ files: ['src/**/*.{ts,tsx}', 'test/**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2022,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
+ {
+ files: ['*.config.ts'],
+ languageOptions: {
+ ecmaVersion: 2022,
+ globals: globals.node,
+ },
+ },
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| files: ["**/*.{ts,tsx}"], | |
| languageOptions: { | |
| ecmaVersion: 2022, | |
| globals: globals.browser, | |
| }, | |
| export default tseslint.config( | |
| { ignores: ['dist', 'coverage', 'playwright-report', 'test-results'] }, | |
| { | |
| extends: [js.configs.recommended, ...tseslint.configs.recommended], | |
| files: ['src/**/*.{ts,tsx}', 'test/**/*.{ts,tsx}'], | |
| languageOptions: { | |
| ecmaVersion: 2022, | |
| globals: globals.browser, | |
| }, | |
| plugins: { | |
| 'react-hooks': reactHooks, | |
| 'react-refresh': reactRefresh, | |
| }, | |
| rules: { | |
| ...reactHooks.configs.recommended.rules, | |
| 'react-refresh/only-export-components': [ | |
| 'warn', | |
| { allowConstantExport: true }, | |
| ], | |
| }, | |
| }, | |
| { | |
| files: ['*.config.ts'], | |
| languageOptions: { | |
| ecmaVersion: 2022, | |
| globals: globals.node, | |
| }, | |
| }, | |
| ); |
🤖 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 `@example-apps/dashrate/eslint.config.js` around lines 11 - 15, The flat ESLint
config block for `files: ["**/*.{ts,tsx}"]` is too broad and applies browser
globals to `playwright.config.ts`, causing Node-only references like
`process.env.CI` to fail linting. Update the config in `eslint.config.js` by
either narrowing this browser-scoped block to only app/test source files or
adding a separate Node-scoped override for `playwright.config.ts`, keeping the
browser globals tied to the correct sources and using the existing flat-config
structure.
| - the total review count uses the standalone `resourceId` index (`countable: "countable"`) | ||
| - the rating distribution and the `rating == N` filter use the compound `resourceId + rating` index | ||
| (`countable: "countable"` plus `rangeCountable: true`) | ||
|
|
||
| Neither aggregate index uses `summable`: the count/sum/average shown per resource is computed in JS | ||
| from the grouped distribution count, so a single grouped `count` query backs both the histogram and | ||
| the average. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Clarify which aggregate values come from the grouped count.
Lines 50-52 say the total review count uses the standalone resourceId count index, but Lines 54-56 then say the displayed count/sum/average all come from the grouped distribution query. Those two descriptions can't both be true, so the README is currently teaching the wrong query plan.
✏️ Suggested wording
-Neither aggregate index uses `summable`: the count/sum/average shown per resource is computed in JS
-from the grouped distribution count, so a single grouped `count` query backs both the histogram and
-the average.
+Neither aggregate index uses `summable`: the displayed average is computed in JS from the grouped
+distribution count, while the total review count comes from the standalone `resourceId` count
+index.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - the total review count uses the standalone `resourceId` index (`countable: "countable"`) | |
| - the rating distribution and the `rating == N` filter use the compound `resourceId + rating` index | |
| (`countable: "countable"` plus `rangeCountable: true`) | |
| Neither aggregate index uses `summable`: the count/sum/average shown per resource is computed in JS | |
| from the grouped distribution count, so a single grouped `count` query backs both the histogram and | |
| the average. | |
| - the total review count uses the standalone `resourceId` index (`countable: "countable"`) | |
| - the rating distribution and the `rating == N` filter use the compound `resourceId + rating` index | |
| (`countable: "countable"` plus `rangeCountable: true`) | |
| Neither aggregate index uses `summable`: the displayed average is computed in JS from the grouped | |
| distribution count, while the total review count comes from the standalone `resourceId` count | |
| index. |
🤖 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 `@example-apps/dashrate/README.md` around lines 50 - 56, The README description
of aggregate queries is inconsistent about where the total review count comes
from; update the wording in the dashrate README to make the query plan
consistent. Use the existing aggregate/index terms already mentioned there
(`resourceId`, `rating`, `countable`, `rangeCountable`, `summable`) and clarify
whether the standalone count index is only for total counts or whether the
grouped count query is the single source for histogram, sum, and average so the
reader sees one coherent explanation.
| }) { | ||
| return ( | ||
| <> | ||
| {status && <p className="status">{status}</p>} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Announce status changes to assistive tech.
The status message is runtime feedback, but it's rendered as a plain <p>, so screen readers will usually miss updates. Add role="status" or an aria-live region here.
🤖 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 `@example-apps/dashrate/src/components/AppNotices.tsx` at line 10, The status
message in AppNotices is rendered as a plain paragraph, so assistive tech may
not announce updates. Update the status rendering in AppNotices to use an
accessible live region, such as adding role="status" or an aria-live attribute
to the existing status element, so changes are announced when status updates at
runtime.
| <p className="notice"> | ||
| No default contract is bundled yet. Sign in and register a DashRate | ||
| contract, or paste an existing contract ID in Settings. | ||
| </p> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Update the no-contract notice to match the shipped default contract.
The PR objective says DashRate ships a default testnet contract ID, so this message is misleading whenever hasContract is false. Reword it to describe a missing or cleared active contract configuration instead of saying none is bundled.
🤖 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 `@example-apps/dashrate/src/components/AppNotices.tsx` around lines 12 - 15,
Update the notice in AppNotices so it no longer says “No default contract is
bundled yet,” since DashRate now ships a default testnet contract ID. Reword the
message to describe a missing or cleared active contract configuration instead,
while keeping the guidance about signing in, registering a contract, or pasting
an existing contract ID in Settings. Use the notice markup in AppNotices as the
target for the text change.
| const historyOpen = history.length > 0; | ||
| const displayRating = hoverRating ?? rating ?? 0; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
The history toggle never gets a real “close” path.
historyOpen is derived only from history.length, but the button always calls onLoadHistory. Once history is loaded, the label flips to “Hide previous versions” even though this component still invokes the load callback and has no explicit way to collapse the section. Add an explicit expanded state/callback, or make the prop contract unambiguously load-only.
Also applies to: 99-112
🤖 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 `@example-apps/dashrate/src/components/ReviewForm.tsx` around lines 36 - 37,
The history toggle logic in ReviewForm is load-only right now, but the UI label
and state imply a real open/close interaction. Update the ReviewForm prop
contract and toggle handling so the control has an explicit expanded/collapse
state or clearly remains load-only, and make the button behavior match the
displayed label instead of always calling onLoadHistory. Use the existing
ReviewForm component and the historyOpen/displayRating logic as the place to
wire in the new state or callback.
| const fillPercent = value === null ? 0 : Math.max(0, Math.min(5, value)) * 20; | ||
| const label = | ||
| value === null ? "No rating yet" : `${formatAverage(value)} out of 5`; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Clamp the spoken label to the same range as the fill.
fillPercent is bounded to 0–5, but aria-label still uses the raw value. For inputs like 7 or -2, the UI shows a clamped meter while assistive tech announces an impossible rating. Reuse the clamped value for both paths.
🤖 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 `@example-apps/dashrate/src/components/StarMeter.tsx` around lines 10 - 12, The
spoken label in StarMeter is using the raw rating instead of the same clamped
value used for fillPercent, so update the label logic to reuse the bounded 0–5
value for both the visual meter and the aria-label. Fix this in StarMeter by
deriving a single clamped rating from value and using it for both the percentage
fill and the accessible text, while still keeping the null case as the “No
rating yet” label.
| try { | ||
| const result = await sdk.dpns.username(identityId); | ||
| if (typeof result !== "string" || result.length === 0) return null; | ||
| return result.endsWith(".dash") ? result.slice(0, -5) : result; | ||
| } catch { | ||
| return null; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Don’t collapse lookup failures into the same null used for “no DPNS name”.
Lines 16-21 make transient SDK failures indistinguishable from a confirmed miss. useDpnsNames then caches that null and stops retrying the same identity, so a temporary failure can permanently degrade display names until reload. Please keep null for true “no name” results and surface lookup failures separately so the hook can retry them.
🤖 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 `@example-apps/dashrate/src/dash/resolveDpnsName.ts` around lines 16 - 21, The
resolveDpnsName helper currently returns null for both a real “no DPNS name”
result and for SDK lookup failures, which causes useDpnsNames to cache transient
errors as permanent misses. Update resolveDpnsName to distinguish a successful
empty result from an exception thrown by sdk.dpns.username, and return or
surface failures in a separate way so useDpnsNames can retry rather than caching
null; keep the existing normalization logic in resolveDpnsName for valid string
results.
| .sr-only { | ||
| border: 0; | ||
| clip: rect(0 0 0 0); | ||
| clip-path: inset(50%); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Remove the deprecated clip property from .sr-only.
Stylelint is already flagging Line 265. Keeping clip here leaves the stylesheet red even though clip-path and the rest of the visually-hidden rules already cover the behavior.
Suggested fix
.sr-only {
border: 0;
- clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
margin: -1px;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .sr-only { | |
| border: 0; | |
| clip: rect(0 0 0 0); | |
| clip-path: inset(50%); | |
| .sr-only { | |
| border: 0; | |
| clip-path: inset(50%); |
🧰 Tools
🪛 Stylelint (17.13.0)
[error] 265-265: Deprecated property "clip" (property-no-deprecated)
(property-no-deprecated)
🤖 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 `@example-apps/dashrate/src/styles.css` around lines 263 - 266, The .sr-only
accessibility helper still uses the deprecated clip property, which Stylelint
flags. Update the .sr-only rule in the stylesheet to remove clip and keep the
existing clip-path-based visually hidden behavior, preserving the rest of the
rules unchanged.
Source: Linters/SAST tools
| expect(screen.getByRole("spinbutton")).toBeTruthy(); // identity index input | ||
| expect(screen.getByText("Current:")).toBeTruthy(); | ||
| fireEvent.click(screen.getByRole("button", { name: /^clear$/i })); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the relevant test and component with line numbers
git ls-files example-apps/dashrate/test/SettingsView.test.tsx example-apps/dashrate/src/components/SettingsView.tsx
printf '\n--- TEST ---\n'
cat -n example-apps/dashrate/test/SettingsView.test.tsx | sed -n '1,220p'
printf '\n--- COMPONENT ---\n'
cat -n example-apps/dashrate/src/components/SettingsView.tsx | sed -n '1,260p'Repository: dashpay/platform-tutorials
Length of output: 11966
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search for the exact text query and related assertions in tests
rg -n 'getByText\("Current:"|Current:|spinbutton|clear' example-apps/dashrate/test/SettingsView.test.tsx example-apps/dashrate/src/components/SettingsView.tsxRepository: dashpay/platform-tutorials
Length of output: 757
Use a matcher that includes the rendered contract ID. getByText("Current:") won’t match the <p> once the <code> value is rendered, so this assertion can fail even when the UI is correct.
Suggested fix
- expect(screen.getByText("Current:")).toBeTruthy();
+ expect(screen.getByText(/Current:\s*c1/i)).toBeTruthy();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| expect(screen.getByRole("spinbutton")).toBeTruthy(); // identity index input | |
| expect(screen.getByText("Current:")).toBeTruthy(); | |
| fireEvent.click(screen.getByRole("button", { name: /^clear$/i })); | |
| expect(screen.getByRole("spinbutton")).toBeTruthy(); // identity index input | |
| expect(screen.getByText(/Current:\s*c1/i)).toBeTruthy(); | |
| fireEvent.click(screen.getByRole("button", { name: /^clear$/i })); |
🤖 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 `@example-apps/dashrate/test/SettingsView.test.tsx` around lines 114 - 116, The
test assertion around the rendered current value is too generic and can break
once the contract ID is displayed inside the same paragraph. Update the
expectation in SettingsView.test.tsx to target the full rendered text for the
“Current:” label together with the contract ID, using the existing screen query
near the clear-button interaction so the assertion matches the actual
SettingsView output.
Summary
Adds DashRate, a React + TypeScript + Vite example app for rating Dash Platform tutorial resources on testnet. It's the showcase for Platform 4.0's relational document queries — provable
count, groupedcount(GROUP BY) for the per-star distribution, range counts, andwherefiltering — and joins the existing example apps (dashnote, dashmint-lab, dashproof-lab).A review is one mutable
reviewdocument per identity per resource: a required 1–5rating, an optionalreviewText, and aresourceIdpointing at a catalog entry. The unique$ownerId + resourceIdindex means saving again edits the existing document rather than duplicating it, and the contract keeps history so prior revisions are viewable. Read-only browsing works without signing in; writing a review requires a mnemonic in Settings.What's included
resources/my-reviews/settings/how): a sidebar resource list plus a detail panel with the aggregate rating, a per-star distribution histogram (click a bar to filter), a review composer, recent reviews, and per-review revision history.App.tsxorchestrates; SDK concerns live one-per-file undersrc/dash/, data fetching insrc/hooks/, presentational components insrc/components/, pure utilities insrc/lib/.countover acountableresourceIdindex; groupedcountover[resourceId, rating](rangeCountable) for the distribution, with the average derived in JS from the per-star counts (nosum/averagequery);rating == Nwherefiltering covered by the same index.src/dash/andsrc/lib/; component tests (@testing-library/react+ jsdom) and hook tests (renderHook, including the request-id stale-response guards); and a read-only Playwright e2e smoke suite (smoke,settings). 152 tests; ~82% statement coverage.eslint.config.js, tsconfig project refs,vite.config.ts, and CI (dashrate-ci.ymlruns test + build); listed in the example-apps README.Notes
DEFAULT_CONTRACT_IDships a working testnet review contract; Settings can register a fresh one and switch to it.Summary by CodeRabbit
New Features
Documentation
Chores