diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f55dd7..f5806de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Message purge — "Purge Old" form on the channel browser deletes all messages older than 1, 7, or 30 days; "Purge Channel" button on the per-channel message list deletes all messages for that channel; both redirect to the channel browser after purging - Message search — channel browser (`GET /cable`) accepts `?q=` to filter the channel list by name substring; per-channel message list (`GET /cable/channels/:channel_hash`) accepts `?q=` to filter messages by payload substring; both show a contextual empty state and a Clear link when a search is active - Per-channel message list — `GET /cable/channels/:channel_hash` shows a paginated, reverse-chronological list of `SolidCable::Message` records for a specific channel; each row shows the message ID, a truncated payload preview (120 chars), and relative sent time with exact timestamp on hover; channel names in the channel browser are now links to their message list - Solid Cable channel browser — `GET /cable` lists all distinct channels with per-channel message count and last-message timestamp, ordered by most recent activity; a total-messages stat and channel-count stat are shown at the top; empty state shown when no messages exist; Cable subnav (Overview) added to the layout diff --git a/README.md b/README.md index 60334bc..454c58d 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,8 @@ Filters are preserved when switching between status tabs (Ready / Scheduled / Ru ### Features - **Channel browser** — `GET /cable` lists all active channels with per-channel message count and last-message timestamp, ordered by most recent activity; supports `?q=` filtering by channel name substring; empty state shown when no messages exist -- **Per-channel message list** — `GET /cable/channels/:channel_hash` shows a paginated, reverse-chronological list of that channel's `SolidCable::Message` records; each row shows the message ID, a truncated payload preview (120 chars) with the full payload on hover, and a relative sent time with the exact timestamp on hover; supports `?q=` filtering by payload substring +- **Per-channel message list** — `GET /cable/channels/:channel_hash` shows a paginated, reverse-chronological list of that channel's `SolidCable::Message` records; each row shows the message ID, a truncated payload preview (120 chars) with the full payload on hover, and a relative sent time with the exact timestamp on hover; supports `?q=` filtering by payload substring; **Purge Channel** button deletes all messages for the channel +- **Message purge** — "Purge Old" form on the channel browser deletes all messages older than 1, 7, or 30 days; confirmation prompt before any destructive action --- diff --git a/ROADMAP.md b/ROADMAP.md index 27fb30d..934d439 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -11,7 +11,6 @@ The path to v1.0.0 is staged: first achieve feature parity with `solid_queue_das > _Surface what's actually flowing through Action Cable._ ### Added -- **Message purge** — delete all messages for a channel or all messages older than N days - **Stats dashboard card** — expand the overview card to include messages per hour, oldest pending message age, and top channels by volume - **Cable timeline** — 24-hour chart of message volume diff --git a/app/assets/stylesheets/solid_stack_web/_08_filters.css b/app/assets/stylesheets/solid_stack_web/_08_filters.css index 3b4dfd4..9e78bc4 100644 --- a/app/assets/stylesheets/solid_stack_web/_08_filters.css +++ b/app/assets/stylesheets/solid_stack_web/_08_filters.css @@ -30,6 +30,12 @@ cursor: pointer; } +.sqw-inline-form { + display: inline-flex; + align-items: center; + gap: 0.4rem; +} + .sqw-period-filter { display: flex; border: 1px solid var(--border); diff --git a/app/controllers/solid_stack_web/cable/channel_purges_controller.rb b/app/controllers/solid_stack_web/cable/channel_purges_controller.rb new file mode 100644 index 0000000..84033e7 --- /dev/null +++ b/app/controllers/solid_stack_web/cable/channel_purges_controller.rb @@ -0,0 +1,8 @@ +module SolidStackWeb + class Cable::ChannelPurgesController < ApplicationController + def destroy + ::SolidCable::Message.where(channel_hash: params[:channel_hash]).delete_all + redirect_to cable_path, notice: "All messages for this channel have been purged." + end + end +end diff --git a/app/controllers/solid_stack_web/cable/purges_controller.rb b/app/controllers/solid_stack_web/cable/purges_controller.rb new file mode 100644 index 0000000..7dabde0 --- /dev/null +++ b/app/controllers/solid_stack_web/cable/purges_controller.rb @@ -0,0 +1,9 @@ +module SolidStackWeb + class Cable::PurgesController < ApplicationController + def destroy + days = [params[:older_than].to_i, 1].max + ::SolidCable::Message.where("created_at < ?", days.days.ago).delete_all + redirect_to cable_path, notice: "Messages older than #{days} #{days == 1 ? "day" : "days"} purged." + end + end +end diff --git a/app/views/solid_stack_web/cable/index.html.erb b/app/views/solid_stack_web/cable/index.html.erb index 4bd9d43..5e9e1e6 100644 --- a/app/views/solid_stack_web/cable/index.html.erb +++ b/app/views/solid_stack_web/cable/index.html.erb @@ -1,5 +1,14 @@ -