Completing a step removes stalled status from UI

Add `updatedAt` to stalled bubble options so JS can check if the card
was recently updated, matching the `Card::Stallable#stalled?`
logic. Refresh the bubble via Turbo Stream when a step is updated.

This should have been part of #1625

Fixes https://app.fizzy.do/5986089/cards/3668
This commit is contained in:
Mike Dalessio
2026-01-16 09:56:10 -05:00
parent 002149a1a7
commit 9c76002bc1
5 changed files with 40 additions and 1 deletions
+1
View File
@@ -16,6 +16,7 @@ module EntropyHelper
{
stalledAfterDays: card.entropy.days_before_reminder,
lastActivitySpikeAt: card.last_activity_spike_at.iso8601,
updatedAt: card.updated_at.iso8601,
action: "Stalled"
}
end
@@ -52,8 +52,11 @@ export default class extends Controller {
this.#show()
}
// Keep in sync with Card::Stallable#stalled? in app/models/card/stallable.rb
get #isStalled() {
return this.stalledValue.lastActivitySpikeAt && signedDifferenceInDays(new Date(this.stalledValue.lastActivitySpikeAt), new Date()) > this.stalledValue.stalledAfterDays
return this.stalledValue.lastActivitySpikeAt &&
signedDifferenceInDays(new Date(this.stalledValue.lastActivitySpikeAt), new Date()) > this.stalledValue.stalledAfterDays &&
signedDifferenceInDays(new Date(this.stalledValue.updatedAt), new Date()) > this.stalledValue.stalledAfterDays
}
#showStalled() {
+1
View File
@@ -13,6 +13,7 @@ module Card::Stallable
after_update_commit :detect_activity_spikes_later, if: :should_detect_activity_spikes?
end
# Keep in sync with #isStalled in app/javascript/controllers/bubble_controller.js
def stalled?
if activity_spike.present?
open? && last_activity_spike_at < STALLED_AFTER_LAST_SPIKE_PERIOD.ago && updated_at < STALLED_AFTER_LAST_SPIKE_PERIOD.ago
@@ -1,3 +1,7 @@
<%= turbo_stream.replace @step do %>
<%= render "cards/steps/step", step: @step %>
<% end %>
<%= turbo_stream.replace dom_id(@card, "bubble") do %>
<%= render "cards/display/preview/bubble", card: @card %>
<% end %>
+30
View File
@@ -0,0 +1,30 @@
require "test_helper"
class EntropyHelperTest < ActionView::TestCase
test "stalled_bubble_options_for returns nil when card has no activity spike" do
assert_nil stalled_bubble_options_for(cards(:logo))
end
test "stalled_bubble_options_for returns options when card has activity spike" do
card = cards(:logo)
card.create_activity_spike!
options = stalled_bubble_options_for(card)
assert_not_nil options
assert_equal card.last_activity_spike_at.iso8601, options[:lastActivitySpikeAt]
end
test "stalled_bubble_options_for includes updatedAt for client-side staleness check" do
card = cards(:logo)
card.create_activity_spike!
travel_to 3.months.from_now
# Touch the card to simulate step completion
card.touch
options = stalled_bubble_options_for(card)
# The helper must include updatedAt so JS can check if card was recently updated
assert_equal card.updated_at.iso8601, options[:updatedAt]
end
end