Skip to content

CC-1717 #2816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: update-course-page-code-examples-test
Choose a base branch
from
Open

CC-1717 #2816

wants to merge 11 commits into from

Conversation

ryan-gang
Copy link
Contributor

@ryan-gang ryan-gang commented May 1, 2025

Checklist:

  • I've thoroughly self-reviewed my changes
  • I've added tests for my changes, unless they affect admin-only areas (or are otherwise not worth testing)
  • I've verified any visual changes using Percy (add a commit with [percy] in the message to trigger)

Summary by CodeRabbit

  • Refactor

    • Streamlined vote handling for community solution cards by consolidating upvote and downvote logic into a unified feedback section, removing separate upvote and downvote button components.
    • Improved UI responsiveness by disabling voting buttons while actions are processing and updating success message display logic.
    • Enhanced vote state management for more accurate and immediate feedback.
  • Style

    • Updated tooltip text for voting buttons to provide clearer feedback on how user input influences example visibility.
  • Tests

    • Adjusted acceptance tests to match updated tooltip text for voting buttons.

Copy link

linear bot commented May 1, 2025

@ryan-gang ryan-gang self-assigned this May 1, 2025
Copy link
Contributor

coderabbitai bot commented May 1, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update refactors the voting functionality for community solution cards within a course stage step. The upvote and downvote button components are removed, and their logic is consolidated into the FeedbackSection component. Voting state is now derived directly from the solution model, and vote actions are managed via ember-concurrency tasks for improved UI responsiveness and feedback. Metadata for upvotes and downvotes is now passed explicitly through component hierarchies. The acceptance tests are updated to reflect new tooltip messages for the voting buttons.

Changes

File(s) Change Summary
app/components/course-page/course-stage-step/community-solution-card/upvote-button.hbs,
app/components/course-page/course-stage-step/community-solution-card/upvote-button.ts,
app/components/course-page/course-stage-step/community-solution-card/downvote-button.hbs,
app/components/course-page/course-stage-step/community-solution-card/downvote-button.ts
Deleted upvote and downvote button component files, removing their templates and logic.
app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts,
app/components/course-page/course-stage-step/community-solution-card/feedback-section.hbs
Refactored voting logic: removed tracked state, added computed properties for vote state, replaced action handlers with ember-concurrency tasks, updated UI bindings, and changed success message display trigger.
app/components/course-page/course-stage-step/community-solution-card/content.hbs,
app/components/course-page/course-stage-step/community-solution-card/index.hbs
Updated to pass @metadataForDownvote, @metadataForUpvote, and @solution arguments to subcomponents.
app/components/course-page/course-stage-step/community-solution-card/content.ts Extended component argument interface to include optional metadataForDownvote and metadataForUpvote.
app/components/course-page/course-stage-step/community-solution-card/header.hbs Removed commented-out block for upvote/downvote buttons in the header.
tests/acceptance/course-page/code-examples/vote-test.js Updated tooltip text assertions for upvote and downvote buttons in acceptance tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant FeedbackSection
    participant SolutionModel

    User->>FeedbackSection: Click Upvote or Downvote
    alt Upvote
        FeedbackSection->>FeedbackSection: handleUpvoteClickTask
        alt Already upvoted
            FeedbackSection->>SolutionModel: unvote()
        else Not yet upvoted
            FeedbackSection->>SolutionModel: upvote(metadataForUpvote)
            FeedbackSection->>FeedbackSection: flashSuccessMessageTask
        end
    else Downvote
        FeedbackSection->>FeedbackSection: handleDownvoteClickTask
        alt Already downvoted
            FeedbackSection->>SolutionModel: unvote()
        else Not yet downvoted
            FeedbackSection->>SolutionModel: downvote(metadataForDownvote)
            FeedbackSection->>FeedbackSection: flashSuccessMessageTask
        end
    end
Loading

Poem

In the warren of code where solution cards dwell,
The upvote and downvote buttons bid farewell.
Now feedback flows in a streamlined dance,
With tasks and metadata given a chance.
Tooltips are clearer, the UI more bright—
A bunny’s delight in code set right!
🐇✨


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented May 1, 2025

Test Results

  1 files  ±0    1 suites  ±0   7m 33s ⏱️ -46s
625 tests +1  579 ✅ +3  45 💤 ±0  1 ❌ +1 
625 runs  +1  579 ✅ +6  45 💤 ±0  1 ❌  - 2 

For more details on these failures, see this check.

Results for commit 709cd3f. ± Comparison against base commit c4f2f92.

♻️ This comment has been updated with latest results.

Copy link

codecov bot commented May 1, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
580 1 579 45
View the top 1 failed test(s) by shortest run time
Chrome 135.0 Global error: Uncaught Error: Mirage: Your app tried to POST 'https://test-backend.ngrok.io/api/v1/community-course-stage-solutions/1/unvote', but there was no route defined to handle this request. Define a route for this endpoint in your routes() config. Did you forget to define a namespace? The existing namespace is undefined at http://localhost:7357/assets/chunk.24a6e7e9a32858ba35e8.js, line 83963&#10; While executing test: Acceptance | course-page | code-examples | vote: can downvote code examples &#10;
Stack Traces | 0s run time
No failure message available

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link

codecov bot commented May 1, 2025

Bundle Report

Changes will increase total bundle size by 253 bytes (0.0%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
client-array-push 36.58MB 253 bytes (0.0%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: client-array-push

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/chunk.*.js 101 bytes 2.84MB 0.0%
assets/chunk.*.js 152 bytes 50.13kB 0.3%

Files in assets/chunk.*.js:

  • ./models/community-course-stage-solution.ts → Total Size: 9.46kB

@ryan-gang
Copy link
Contributor Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented May 1, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
app/components/course-page/course-stage-step/community-solution-card/feedback-section.hbs (2)

4-12: Decouple flash-message visibility from the task lifecycle to prevent UI flicker

animated-if keys off flashSuccessMessageTask.isRunning.
If a user clicks “Helpful/Not helpful” several times in quick succession, keepLatest: true will cancel the running task and start a new one, momentarily setting isRunning to false and causing the “Thanks for your feedback!” line to flicker.

A small tracked boolean dedicated to the banner’s visibility avoids this side-effect and makes the intent clearer.

-{{#animated-if this.flashSuccessMessageTask.isRunning …}}
+{{#animated-if this.showFlashMessage …}}

Inside the task:

 this.showFlashMessage = true;
 await timeout(1500);
 this.showFlashMessage = false;

This separates UI state from the task state while preserving the 1.5 s display duration.


18-22: Add explicit type="button" and ARIA labels for accessibility

The TertiaryButton likely renders a native <button> element.
Adding type="button" prevents unintended form submission if the component is ever nested inside a <form>.
An aria-label (or aria-pressed to convey toggle state) will also improve screen-reader support.

-<TertiaryButton
+<TertiaryButton
+  type="button"
+  aria-label={{if this.currentUserHasUpvoted "Remove helpful vote" "Mark as helpful"}}

Apply the same pattern to the Not helpful button.

app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts (1)

42-49: DRY: Extract a shared helper to reduce duplication

handleUpvoteClickTask and handleDownvoteClickTask are nearly identical. A private method (e.g., _toggleVote) receiving the “direction” and metadata would reduce maintenance cost and make future changes (e.g., adding analytics) one-liner updates.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 45-45: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L45
Added line #L45 was not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4f2f92 and f5d17a0.

📒 Files selected for processing (11)
  • app/components/course-page/course-stage-step/community-solution-card/content.hbs (1 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/content.ts (1 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/downvote-button.hbs (0 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/downvote-button.ts (0 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/feedback-section.hbs (2 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts (1 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/header.hbs (0 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/index.hbs (1 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/upvote-button.hbs (0 hunks)
  • app/components/course-page/course-stage-step/community-solution-card/upvote-button.ts (0 hunks)
  • tests/acceptance/course-page/code-examples/vote-test.js (2 hunks)
💤 Files with no reviewable changes (5)
  • app/components/course-page/course-stage-step/community-solution-card/header.hbs
  • app/components/course-page/course-stage-step/community-solution-card/upvote-button.hbs
  • app/components/course-page/course-stage-step/community-solution-card/downvote-button.hbs
  • app/components/course-page/course-stage-step/community-solution-card/upvote-button.ts
  • app/components/course-page/course-stage-step/community-solution-card/downvote-button.ts
🧰 Additional context used
🪛 ESLint
tests/acceptance/course-page/code-examples/vote-test.js

[error] 52-52: Replace "Your·feedback·helps·us·surface·better·examples." with 'Your·feedback·helps·us·surface·better·examples.'

(prettier/prettier)


[error] 97-97: Replace "Your·feedback·helps·us·identify·examples·that·need·review." with 'Your·feedback·helps·us·identify·examples·that·need·review.'

(prettier/prettier)

🪛 GitHub Actions: Test
tests/acceptance/course-page/code-examples/vote-test.js

[error] 52-52: Prettier formatting error: Replace double quotes with single quotes. (prettier/prettier)


[error] 97-97: Prettier formatting error: Replace double quotes with single quotes. (prettier/prettier)


[error] Prettier formatting check failed. Run 'prettier --write' to fix code style issues.

🪛 GitHub Check: codecov/patch
app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts

[warning] 36-36: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L36
Added line #L36 was not covered by tests


[warning] 45-45: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L45
Added line #L45 was not covered by tests

🔇 Additional comments (6)
app/components/course-page/course-stage-step/community-solution-card/index.hbs (1)

18-19: Consistent metadata passing looks good.

The addition of metadata arguments to the Content component ensures consistent data flow for voting functionality across the component hierarchy, matching what's already passed to the Header component.

app/components/course-page/course-stage-step/community-solution-card/content.ts (1)

18-19: Interface extension looks good.

The addition of metadata arguments to the interface properly types the data being passed through the component hierarchy, supporting the consolidated voting functionality.

app/components/course-page/course-stage-step/community-solution-card/content.hbs (1)

89-94: Proper metadata forwarding to FeedbackSection.

The component now correctly passes the voting metadata and solution data to the FeedbackSection component, supporting the refactored voting functionality.

app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts (3)

19-25: Guard against undefined vote arrays

currentUserUpvotes/currentUserDownvotes are assumed to be arrays, but if the server omits them (e.g., during an optimistic render) length will throw. A small defensive tweak keeps the component safe:

-return this.args.solution.currentUserDownvotes.length > 0;
+return (this.args.solution.currentUserDownvotes ?? []).length > 0;

Do the same for currentUserUpvotes.


27-32: Good use of an isolated task for the success banner

The refactor cleanly scopes banner timing logic and avoids leaking state—nice!


33-49: Add unit/acceptance tests for the new vote-toggle paths

Codecov flagged lines 36 and 45 as uncovered.
At minimum, test that:

  1. Clicking Helpful when not previously up-voted triggers solution.upvote, shows the banner for ~1.5 s and disables the button while the task runs.
  2. Clicking again calls solution.unvote.
  3. Error paths surface a message (once implemented).

This will protect against regressions in the concurrency logic.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 36-36: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L36
Added line #L36 was not covered by tests


[warning] 45-45: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L45
Added line #L45 was not covered by tests

Comment on lines 33 to 41
handleUpvoteClickTask = task({ keepLatest: true }, async () => {
if (this.currentUserHasUpvoted) {
await this.args.solution.unvote({});
} else {
await this.args.solution.upvote(this.args.metadataForUpvote || {});
this.flashSuccessMessageTask.perform();
}
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Surface API failures to the user & keep button state in sync

If solution.upvote/unvote rejects (network error, 4xx, etc.) the task will fail silently; the button re-enables but the vote state won’t change, leaving users confused.

Consider wrapping the body in try/catch, showing a toast or banner, and optionally rolling back local state:

-handleUpvoteClickTask = task({ keepLatest: true }, async () => {
+handleUpvoteClickTask = task({ keepLatest: true }, async () => {
+  try {
     if (this.currentUserHasUpvoted) {
       await this.args.solution.unvote({});
     } else {
       await this.args.solution.upvote(this.args.metadataForUpvote || {});
       this.flashSuccessMessageTask.perform();
     }
+  } catch (e) {
+    // TODO: surface a user-friendly error message
+    console.error('Failed to toggle upvote', e);
+  }
 });

Replicate the pattern for the downvote task.

📝 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.

Suggested change
handleUpvoteClickTask = task({ keepLatest: true }, async () => {
if (this.currentUserHasUpvoted) {
await this.args.solution.unvote({});
} else {
await this.args.solution.upvote(this.args.metadataForUpvote || {});
this.flashSuccessMessageTask.perform();
}
});
handleUpvoteClickTask = task({ keepLatest: true }, async () => {
try {
if (this.currentUserHasUpvoted) {
await this.args.solution.unvote({});
} else {
await this.args.solution.upvote(this.args.metadataForUpvote || {});
this.flashSuccessMessageTask.perform();
}
} catch (e) {
// TODO: surface a user-friendly error message
console.error('Failed to toggle upvote', e);
}
});
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 36-36: app/components/course-page/course-stage-step/community-solution-card/feedback-section.ts#L36
Added line #L36 was not covered by tests

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.

1 participant