Skip to content

Fix status page logic to distinguish onboarding from active users#288

Open
dreikanter wants to merge 25 commits intomainfrom
status-states
Open

Fix status page logic to distinguish onboarding from active users#288
dreikanter wants to merge 25 commits intomainfrom
status-states

Conversation

@dreikanter
Copy link
Owner

@dreikanter dreikanter commented Nov 30, 2025

Changes:

  • Use user.state to distinguish onboarding flow from active users with deactivated tokens.
  • Transition user from onboarding to active state on first feed creation.
  • Show warning banner instead of Welcome message when active user has no active tokens.
  • Add manual testing guide for onboarding scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 30, 2025

Walkthrough

Feed creation now activates an onboarding user upon successful save; status rendering switched to use current_user with helper-driven locals and explicit onboarding branches; feed identification rendering moved to a polling variant and several Turbo Stream actions changed from replace to update; tests and onboarding docs added/expanded.

Changes

Cohort / File(s) Summary
Controllers — feeds
app/controllers/feeds_controller.rb
FeedsController#create now activates current_user when they are onboarding after a successful feed save; tests added for onboarding→active transition, no-op for already-active users, and rollback on save failure.
Controllers — statuses & application helper
app/controllers/statuses_controller.rb, app/controllers/application_controller.rb
StatusesController#show replaced instance variables with render locals and private helpers (recent_events, has_active_tokens?, no_feeds?) and references current_user; ApplicationController exposes current_user to views via helper_method :current_user.
Controllers — feed details / turbo + polling
app/controllers/feed_details_controller.rb
Processing now uses identification_loading_poll (polling partial) in timeout-safe flows; Turbo Stream responses changed from replaceupdate (identification_success, identification_error); identification_loading target changed to feed-form-wrapper.
Views / Partials — feed form & loading states
app/views/feeds/_form_collapsed.html.erb, app/views/feeds/_form_expanded.html.erb, app/views/feeds/_identification_loading.html.erb, app/views/feeds/_identification_loading_poll.html.erb, app/views/feeds/_identification_error.html.erb, app/views/statuses/show.html.erb, app/views/feeds/edit.html.erb, app/views/feeds/new.html.erb
Added outer feed-form-wrapper and inner feed-form where applicable; moved polling data attributes to wrapper; added _identification_loading_poll partial; restructured loading/error partials to use update targets; statuses/show switched to current_user, added onboarding branches and active-user warning; layout width adjusted in edit/new.
Components / Strings
app/components/feed_stats_component.rb
Adjusted labels: "Most recent publication" → "Latest imported post", "Recent" → "Latest", fallback "No posts imported" → "None".
Tests — controller & component coverage
test/controllers/feeds_controller_test.rb, test/controllers/statuses_controller_test.rb, test/controllers/feed_details_controller_test.rb, test/components/feed_stats_component_test.rb
New/expanded tests for feed-creation onboarding transitions, richer status-page state coverage (multiple onboarding/active scenarios), updated expectation for Turbo Stream update in feed details tests, and updated string assertions for feed stats component.
Documentation
docs/onboarding_test_manual.md
New onboarding testing manual with prerequisites, nine test cases, one-liner setup/cleanup commands, browser-agent notes, expected UI verifications, and reset guidance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify FeedsController#create transactional behavior so user activation occurs only after successful feed persistence and rolls back on failure.
  • Check StatusesController helper implementations and that switching to current_user preserves intended view semantics.
  • Confirm Turbo Stream change (replace → update) and feed-form-wrapper/feed-form id changes do not break client-side JS, polling behavior, or accessibility.
  • Validate tests and onboarding doc commands for correctness and idempotence.

Possibly related PRs

Poem

🐇 I nudged a feed into the light,
Spun a tiny spinner, checked it right.
Onboarding blinked and stretched awake,
Tests hopped in for goodness' sake.
Hooray — a dashboard, crisp and bright.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing status page logic to distinguish onboarding users from active users, which is directly reflected in the controller and view modifications.
Description check ✅ Passed The description accurately outlines the key changes: using user.state for distinction, transitioning users on first feed creation, showing appropriate UI based on user state, and adding testing documentation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch status-states

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 984c29b and b6e5a0c.

📒 Files selected for processing (8)
  • app/components/feed_stats_component.rb (2 hunks)
  • app/views/feeds/_form_expanded.html.erb (2 hunks)
  • app/views/feeds/_identification_error.html.erb (1 hunks)
  • app/views/feeds/_identification_loading.html.erb (1 hunks)
  • app/views/feeds/_identification_loading_poll.html.erb (1 hunks)
  • app/views/feeds/edit.html.erb (1 hunks)
  • app/views/feeds/new.html.erb (1 hunks)
  • test/components/feed_stats_component_test.rb (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/views/feeds/_identification_error.html.erb
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rb,js,jsx,ts,tsx,css,scss,html,erb,slim}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add trailing line breaks to source files (Ruby, JS, CSS, HTML, etc.) unless there is a specific reason not to

Files:

  • app/components/feed_stats_component.rb
  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/edit.html.erb
  • test/components/feed_stats_component_test.rb
  • app/views/feeds/_form_expanded.html.erb
  • app/views/feeds/new.html.erb
  • app/views/feeds/_identification_loading_poll.html.erb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use two-space indentation in code files

Files:

  • app/components/feed_stats_component.rb
  • test/components/feed_stats_component_test.rb
app/views/**/*.{erb,slim,html}

📄 CodeRabbit inference engine (CLAUDE.md)

app/views/**/*.{erb,slim,html}: When writing user-facing text in views, use a friendly but not overly familiar tone, be brief and clear, avoid stiff formal language and unnecessary terminology
Don't expose UI implementation details in user-facing text; avoid terms like 'wizard', 'form', 'dialog', 'modal', 'interface', 'screen'
Keep data-key attributes short and namespaced using the format component.element

Files:

  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/edit.html.erb
  • app/views/feeds/_form_expanded.html.erb
  • app/views/feeds/new.html.erb
  • app/views/feeds/_identification_loading_poll.html.erb
test/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.rb: Prefer lazy test data initialization over eager initialization in setup block using methods with memoization
Use test naming convention test "#method should ..." for unit tests
Prefer data-key attributes for DOM selectors in tests instead of styling classes
Use FactoryBot to create test data

Files:

  • test/components/feed_stats_component_test.rb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (9)
test/components/feed_stats_component_test.rb (1)

46-46: LGTM! Test assertions correctly updated.

The test assertions have been properly updated to match the new component labels introduced in app/components/feed_stats_component.rb.

Also applies to: 56-56, 70-70

app/components/feed_stats_component.rb (2)

30-32: LGTM! Labels are clearer and more specific.

"Latest imported post" better describes what the metric represents compared to "Most recent publication," and "Latest" is appropriately concise for the desktop layout.


89-89: LGTM! Fallback text is now consistent.

The "None" fallback follows the same terse pattern as "Never" on line 81, creating consistency across the component's empty states.

app/views/feeds/_identification_loading_poll.html.erb (1)

1-13: LGTM! Good accessibility and clear messaging.

The loading state uses appropriate ARIA semantics with role="status" and provides clear, friendly feedback to users. The two-line message structure effectively communicates both the current action and expected duration.

app/views/feeds/_identification_loading.html.erb (1)

1-22: LGTM! Well-structured polling setup.

The restructuring cleanly separates polling concerns (outer wrapper with data attributes) from content presentation (inner ff-card). The nested container structure supports the new polling flow introduced elsewhere in the PR.

app/views/feeds/new.html.erb (1)

6-6: LGTM! Layout width adjusted for consistency.

The narrower max-width and removal of centering align with the same change in app/views/feeds/edit.html.erb, creating a consistent layout across feed views.

app/views/feeds/edit.html.erb (1)

6-6: LGTM! Layout width adjusted for consistency.

Matches the same change in app/views/feeds/new.html.erb, ensuring consistent presentation across feed creation and editing views.

app/views/feeds/_form_expanded.html.erb (2)

4-4: LGTM! State attribute supports polling flow.

The data-identification-state="complete" attribute integrates with the polling mechanism defined in the parent wrapper (see _identification_loading.html.erb), allowing the polling to stop when identification is complete.


16-18: LGTM! Standardized alert component.

Replacing the custom info block with the ff-alert ff-alert--info component improves visual consistency across the application while preserving the same user message.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dreikanter
Copy link
Owner Author

@codex review

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codecov
Copy link

codecov bot commented Nov 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.48%. Comparing base (f88f54b) to head (b6e5a0c).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #288   +/-   ##
=======================================
  Coverage   97.47%   97.48%           
=======================================
  Files         157      157           
  Lines        3448     3459   +11     
=======================================
+ Hits         3361     3372   +11     
  Misses         87       87           
Files with missing lines Coverage Δ
app/components/feed_stats_component.rb 100.00% <100.00%> (ø)
app/controllers/application_controller.rb 100.00% <100.00%> (ø)
app/controllers/feed_details_controller.rb 96.07% <100.00%> (+0.16%) ⬆️
app/controllers/feeds_controller.rb 100.00% <100.00%> (ø)
app/controllers/statuses_controller.rb 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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: 1

🧹 Nitpick comments (6)
app/controllers/statuses_controller.rb (1)

4-5: Onboarding flags are correct; consider exists? for consistency/perf

@has_active_tokens = @user.access_tokens.active.any? and @has_feeds = @user.total_feeds_count > 0 match the view’s state logic and are easy to read. For consistency with active_access_tokens? in FeedsController and slightly clearer intent, you might prefer:

@has_active_tokens = @user.access_tokens.active.exists?

Functionally it’s the same here, so this is purely optional.

app/views/statuses/show.html.erb (1)

18-50: State-driven rendering matches onboarding/active requirements; small readability tweak optional

The conditional chain correctly encodes:

  • State 1: onboarding with no active tokens → welcome + “Add FreeFeed token”.
  • State 2: onboarding with active token(s) and no feeds → welcome + “Add feed”.
  • States 3/4: non-onboarding → dashboard, with an extra warning for active users without active tokens.

Copy is clear and user-friendly and lines up with tests/manual. If you want to reduce repetition, you could nest on @user.onboarding? once:

<% if @user.onboarding? %>
  <% if !@has_active_tokens %>
    ...
  <% elsif @has_active_tokens && !@has_feeds %>
    ...
  <% end %>
<% else %>
  ...
<% end %>

Current structure is perfectly fine if you prefer it.

app/controllers/feeds_controller.rb (1)

57-61: Good placement of onboarding→active transition inside transaction; consider tying to current_user explicitly

Putting Current.user.active! if Current.user.onboarding? inside the ActiveRecord::Base.transaction that wraps @feed.save! and reset_schedule! is the right place: validation failures won’t leave the user state half-updated, and a raised error will roll back both feed and state.

Since feeds_scope is already current_user.feeds, you might tighten the association and avoid relying on Current here:

user = current_user
user.active! if user.onboarding?

or even @feed.user to make the coupling explicit. Behavior stays the same; this is just for clarity and to avoid surprises if Current.user is ever changed.

test/controllers/feeds_controller_test.rb (1)

170-236: New #create tests cover onboarding transitions and rollback well

The three added tests do a good job of pinning down the intended behavior:

  • Onboarding user with a valid first feed moves to active.
  • Already-active user remains active.
  • Onboarding user stays onboarding when feed validation fails.

They line up with the controller transaction behavior and give nice regression coverage. If you want to tighten them further, you could:

  • In the “transition user from onboarding to active” test, also assert assert_difference("Feed.count", 1) around the POST to document clearly that it’s the first successful feed creation that completes onboarding.
  • In the “rollback state transition” test, keep as-is (it already uses assert_no_difference("Feed.count")).

These are optional; the current tests are already solid.

test/controllers/statuses_controller_test.rb (2)

13-44: State 1–4 status-page tests accurately exercise onboarding and active flows

The new tests for:

  • onboarding state 1 (no active tokens),
  • onboarding state 2 (has token, no feeds),
  • active state 3 (normal dashboard),
  • active state 4 (active user with missing active tokens),

all correctly set up state, tokens, and feeds to match the view’s branching, and assert against the right headings and CTAs. This closely mirrors the documented states and should catch regressions in the onboarding logic.

If you want to make these a bit more future-proof, you could explicitly assert the token count in the state 1/4 setups (e.g., ensure there are 0 active tokens) so the tests don’t start failing unexpectedly if user factories are later changed to pre-create tokens. Not required, just a defensive tweak.


59-187: Stats visibility tests align with data-keys and state gating

The stats-related tests (total_feeds, imported/published posts, most recent post, averages, and “hide stats when no posts”) correctly:

  • Use state: :active + active tokens + feeds when stats should be shown.
  • Use an onboarding user when stats should not appear, matching the view’s branching.
  • Assert against the data-key="stats.*" attributes, which is in line with the preferred selector strategy from the guidelines.

One small improvement you might consider is adding a variant where the user is active with zero posts to explicitly prove that hiding of “most recent post” / “average posts per day” is independent of onboarding vs active state, but the current tests are already quite comprehensive.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f88f54b and 7d3ea43.

📒 Files selected for processing (6)
  • app/controllers/feeds_controller.rb (1 hunks)
  • app/controllers/statuses_controller.rb (1 hunks)
  • app/views/statuses/show.html.erb (3 hunks)
  • docs/onboarding_test_manual.md (1 hunks)
  • test/controllers/feeds_controller_test.rb (1 hunks)
  • test/controllers/statuses_controller_test.rb (12 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{rb,js,jsx,ts,tsx,css,scss,html,erb,slim}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add trailing line breaks to source files (Ruby, JS, CSS, HTML, etc.) unless there is a specific reason not to

Files:

  • app/controllers/statuses_controller.rb
  • test/controllers/feeds_controller_test.rb
  • test/controllers/statuses_controller_test.rb
  • app/controllers/feeds_controller.rb
  • app/views/statuses/show.html.erb
app/controllers/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

Eliminate blank action methods in controllers

Files:

  • app/controllers/statuses_controller.rb
  • app/controllers/feeds_controller.rb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use two-space indentation in code files

Files:

  • app/controllers/statuses_controller.rb
  • test/controllers/feeds_controller_test.rb
  • test/controllers/statuses_controller_test.rb
  • app/controllers/feeds_controller.rb
test/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.rb: Prefer lazy test data initialization over eager initialization in setup block using methods with memoization
Use test naming convention test "#method should ..." for unit tests
Prefer data-key attributes for DOM selectors in tests instead of styling classes
Use FactoryBot to create test data

Files:

  • test/controllers/feeds_controller_test.rb
  • test/controllers/statuses_controller_test.rb
app/views/**/*.{erb,slim,html}

📄 CodeRabbit inference engine (CLAUDE.md)

app/views/**/*.{erb,slim,html}: When writing user-facing text in views, use a friendly but not overly familiar tone, be brief and clear, avoid stiff formal language and unnecessary terminology
Don't expose UI implementation details in user-facing text; avoid terms like 'wizard', 'form', 'dialog', 'modal', 'interface', 'screen'
Keep data-key attributes short and namespaced using the format component.element

Files:

  • app/views/statuses/show.html.erb
🧠 Learnings (1)
📚 Learning: 2025-10-26T17:01:41.639Z
Learnt from: dreikanter
Repo: dreikanter/f2 PR: 163
File: app/controllers/resend_webhooks_controller.rb:76-99
Timestamp: 2025-10-26T17:01:41.639Z
Learning: In the Event model, both the `user` and `subject` attributes are optional. Events can be created and saved with `nil` values for these fields, which is intentional behavior to allow tracking events even when a user cannot be found.

Applied to files:

  • test/controllers/statuses_controller_test.rb
🧬 Code graph analysis (3)
app/controllers/statuses_controller.rb (1)
app/models/user.rb (1)
  • total_feeds_count (94-96)
test/controllers/feeds_controller_test.rb (2)
app/controllers/feeds_controller.rb (2)
  • create (51-67)
  • feed_params (135-146)
test/support/integration_test_helpers.rb (1)
  • sign_in_as (2-4)
app/controllers/feeds_controller.rb (1)
test/controllers/feeds_controller_test.rb (2)
  • user (3-436)
  • user (4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (1)
test/controllers/statuses_controller_test.rb (1)

188-270: Recent-events tests thoroughly cover user scoping, filtering, and limits

The recent-events tests collectively verify:

  • Only the signed-in user’s events are shown.
  • Debug-level and expired events are excluded.
  • The list is capped at 10 items.
  • The section hides entirely when there are no events.

Using data-key="recent_events.<id>" keeps the selectors stable and decoupled from presentation. Given prior learnings that Event#user is optional, asserting behavior both when it’s present (these tests) and when other users’ events exist is particularly useful to guard the Event.where(user: @user).user_relevant.recent.limit(10) query. Based on learnings, this is a good alignment with the intended event model semantics.

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: 0

🧹 Nitpick comments (1)
app/views/feeds/_identification_loading_poll.html.erb (1)

1-12: LGTM: Clean polling status partial.

The structure is appropriate, with good accessibility via role="status". The user-facing messages are clear and friendly.

Add trailing newline per coding guidelines.

The coding guidelines specify that source files should have trailing line breaks.

As per coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a0ade4 and 67d69fd.

📒 Files selected for processing (7)
  • app/controllers/feed_details_controller.rb (3 hunks)
  • app/views/feeds/_form_collapsed.html.erb (1 hunks)
  • app/views/feeds/_form_expanded.html.erb (1 hunks)
  • app/views/feeds/_identification_error.html.erb (1 hunks)
  • app/views/feeds/_identification_loading.html.erb (1 hunks)
  • app/views/feeds/_identification_loading_poll.html.erb (1 hunks)
  • test/controllers/feed_details_controller_test.rb (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/views/feeds/_form_expanded.html.erb
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/feed_details_controller.rb
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rb,js,jsx,ts,tsx,css,scss,html,erb,slim}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add trailing line breaks to source files (Ruby, JS, CSS, HTML, etc.) unless there is a specific reason not to

Files:

  • app/views/feeds/_identification_error.html.erb
  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/_form_collapsed.html.erb
  • test/controllers/feed_details_controller_test.rb
  • app/views/feeds/_identification_loading_poll.html.erb
app/views/**/*.{erb,slim,html}

📄 CodeRabbit inference engine (CLAUDE.md)

app/views/**/*.{erb,slim,html}: When writing user-facing text in views, use a friendly but not overly familiar tone, be brief and clear, avoid stiff formal language and unnecessary terminology
Don't expose UI implementation details in user-facing text; avoid terms like 'wizard', 'form', 'dialog', 'modal', 'interface', 'screen'
Keep data-key attributes short and namespaced using the format component.element

Files:

  • app/views/feeds/_identification_error.html.erb
  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/_form_collapsed.html.erb
  • app/views/feeds/_identification_loading_poll.html.erb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use two-space indentation in code files

Files:

  • test/controllers/feed_details_controller_test.rb
test/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.rb: Prefer lazy test data initialization over eager initialization in setup block using methods with memoization
Use test naming convention test "#method should ..." for unit tests
Prefer data-key attributes for DOM selectors in tests instead of styling classes
Use FactoryBot to create test data

Files:

  • test/controllers/feed_details_controller_test.rb
🧠 Learnings (2)
📚 Learning: 2025-11-29T19:38:34.155Z
Learnt from: CR
Repo: dreikanter/f2 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T19:38:34.155Z
Learning: Applies to app/views/**/*.{erb,slim,html} : Keep `data-key` attributes short and namespaced using the format `component.element`

Applied to files:

  • app/views/feeds/_identification_loading.html.erb
📚 Learning: 2025-11-29T19:38:34.155Z
Learnt from: CR
Repo: dreikanter/f2 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T19:38:34.155Z
Learning: Applies to app/views/**/*.{erb,slim,html} : Don't expose UI implementation details in user-facing text; avoid terms like 'wizard', 'form', 'dialog', 'modal', 'interface', 'screen'

Applied to files:

  • app/views/feeds/_identification_loading.html.erb
🔇 Additional comments (4)
app/views/feeds/_identification_error.html.erb (1)

1-1: LGTM: Consistent with data-driven state handling.

The removal of the id attribute aligns with the shift toward data-attribute-based state management across the feed identification flow.

app/views/feeds/_form_collapsed.html.erb (1)

2-25: LGTM: Wrapper structure enables Turbo Stream updates.

The new wrapper structure with feed-form-wrapper and feed-form IDs is consistent with the broader refactoring and properly nests the form and footer elements.

app/views/feeds/_identification_loading.html.erb (1)

1-21: LGTM: Polling configuration properly externalized to wrapper.

The restructure moves polling configuration to the outer wrapper while simplifying the CardComponent to focus on presentation. The user-facing messages are clear and friendly.

test/controllers/feed_details_controller_test.rb (1)

216-216: LGTM: Test expectation aligns with Turbo Stream update semantics.

The change from action="replace" to action="update" correctly reflects the controller's use of turbo_stream.update for the feed-form target.

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67d69fd and 984c29b.

📒 Files selected for processing (3)
  • app/views/feeds/_identification_error.html.erb (1 hunks)
  • app/views/feeds/_identification_loading.html.erb (1 hunks)
  • app/views/feeds/_identification_loading_poll.html.erb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/views/feeds/_identification_loading_poll.html.erb
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rb,js,jsx,ts,tsx,css,scss,html,erb,slim}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add trailing line breaks to source files (Ruby, JS, CSS, HTML, etc.) unless there is a specific reason not to

Files:

  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/_identification_error.html.erb
app/views/**/*.{erb,slim,html}

📄 CodeRabbit inference engine (CLAUDE.md)

app/views/**/*.{erb,slim,html}: When writing user-facing text in views, use a friendly but not overly familiar tone, be brief and clear, avoid stiff formal language and unnecessary terminology
Don't expose UI implementation details in user-facing text; avoid terms like 'wizard', 'form', 'dialog', 'modal', 'interface', 'screen'
Keep data-key attributes short and namespaced using the format component.element

Files:

  • app/views/feeds/_identification_loading.html.erb
  • app/views/feeds/_identification_error.html.erb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (1)
app/views/feeds/_identification_loading.html.erb (1)

1-18: Polling wrapper structure and timeout math are correct

The restructuring makes sense: the outer #feed-form-wrapper owns the polling controller and its values, while the inner #feed-form+CardComponent is purely presentational. The stop condition selector for [data-identification-state='complete'] and [data-identification-state='error'] aligns correctly with the state-driven partials.

The timeout math checks out:

  • Feed::IDENTIFICATION_POLLING_INTERVAL_MS = 2000 (2 seconds)
  • FeedDetailsController::IDENTIFICATION_TIMEOUT_SECONDS = 30 (30 seconds)
  • Max polls: 30 / 2 = 15 polls, which yields 15 × 2000ms = 30 seconds overall timeout ✓

State consistency is solid: _identification_error.html.erb sets data-identification-state="error" and _form_expanded.html.erb sets data-identification-state="complete", both matching the stop condition reliably.

<div id="feed-form"
data-identification-state="error"
class="rounded-lg border border-slate-200 bg-white px-6 py-8 shadow-sm space-y-6">
<div data-identification-state="error" class="rounded-lg border border-slate-200 bg-white px-6 py-8 shadow-sm space-y-6">
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for any remaining references to feed-form in the codebase
rg -n "feed-form" --hidden

Repository: dreikanter/f2

Length of output: 1399


🏁 Script executed:

# Check the actual file content to see context
cat -n app/views/feeds/_identification_error.html.erb | head -20

Repository: dreikanter/f2

Length of output: 1065


🏁 Script executed:

# Search for all data-identification-state usages to understand the pattern
rg -n "data-identification-state" --hidden

Repository: dreikanter/f2

Length of output: 1624


Critical: Missing id for turbo_stream targets and data-key naming violates guidelines

The removal of the id="feed-form" from this partial breaks turbo_stream updates. The controller at feed_details_controller.rb (lines 8, 100, 110, 120, 129) targets "feed-form" and "feed-form-wrapper" in multiple turbo_stream responses, but _identification_error.html.erb now has no id to match them.

Additionally, the data-identification-state attribute violates the coding guideline for data-keys: it should use the component.element format (e.g., data-feed="error").

Required fixes:

  1. Add id="feed-form" back to the wrapper div or update all turbo_stream targets in the controller to use the data attribute selector
  2. Rename data-identification-state to follow the component.element naming convention

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