diff --git a/engine/app/controllers/coplan/web_push/subscriptions_controller.rb b/engine/app/controllers/coplan/web_push/subscriptions_controller.rb index 5552856..d24b799 100644 --- a/engine/app/controllers/coplan/web_push/subscriptions_controller.rb +++ b/engine/app/controllers/coplan/web_push/subscriptions_controller.rb @@ -17,6 +17,15 @@ def create render json: { id: record.id, created_at: record.created_at }, status: :created end + # GET /web_push/devices + # Renders the device list inside its turbo-frame so the Settings page + # can refresh just that section after enabling/disabling on this browser. + def devices + @web_push_subscriptions = current_user.web_push_subscriptions.order(created_at: :desc) + render partial: "coplan/settings/settings/devices", + locals: { web_push_subscriptions: @web_push_subscriptions } + end + # DELETE /web_push/subscription # Body: { subscription: { endpoint } } def destroy diff --git a/engine/app/javascript/controllers/coplan/web_push_settings_controller.js b/engine/app/javascript/controllers/coplan/web_push_settings_controller.js index b15aa62..60ec3a7 100644 --- a/engine/app/javascript/controllers/coplan/web_push_settings_controller.js +++ b/engine/app/javascript/controllers/coplan/web_push_settings_controller.js @@ -5,6 +5,7 @@ import * as WebPush from "coplan/web_push" // browser's subscription state (which the server can't know — it's per-device). export default class extends Controller { static targets = ["enableButton", "disableButton", "status"] + static values = { devicesUrl: { type: String, default: "" } } async connect() { await this._refresh() @@ -15,6 +16,7 @@ export default class extends Controller { try { await WebPush.subscribe() this._setStatus("Notifications enabled on this device.") + this._reloadDevices() } catch (err) { this._setStatus(this._friendlyError(err)) } @@ -26,12 +28,23 @@ export default class extends Controller { try { await WebPush.unsubscribe() this._setStatus("Notifications disabled on this device.") + this._reloadDevices() } catch (err) { this._setStatus(this._friendlyError(err)) } await this._refresh() } + // Tell the device-list turbo-frame to refetch itself so the row for this + // browser appears (or disappears) without a full page reload. + _reloadDevices() { + if (!this.devicesUrlValue) return + const frame = document.getElementById("web-push-devices") + if (!frame) return + // Setting src triggers a fetch even when the URL hasn't changed. + frame.src = this.devicesUrlValue + } + // ---- internals ---- async _refresh() { diff --git a/engine/app/views/coplan/settings/settings/_devices.html.erb b/engine/app/views/coplan/settings/settings/_devices.html.erb new file mode 100644 index 0000000..ae1fa80 --- /dev/null +++ b/engine/app/views/coplan/settings/settings/_devices.html.erb @@ -0,0 +1,28 @@ +<%# Per-device list rendered both in-page (initial load) and as a turbo-frame %> +<%# response after the Stimulus controller refreshes it post-enable/disable. %> +<%= turbo_frame_tag "web-push-devices" do %> + <% if web_push_subscriptions.any? %> +
+
Devices receiving notifications
+ +

+ To remove a device, sign in to CoPlan from that browser and click "Disable on this device". +

+
+ <% end %> +<% end %> diff --git a/engine/app/views/coplan/settings/settings/_notifications.html.erb b/engine/app/views/coplan/settings/settings/_notifications.html.erb index 03ed2e4..c2fa0b4 100644 --- a/engine/app/views/coplan/settings/settings/_notifications.html.erb +++ b/engine/app/views/coplan/settings/settings/_notifications.html.erb @@ -1,6 +1,8 @@ <% return unless CoPlan.configuration.web_push_configured? %> -
+
Browser notifications
@@ -28,28 +30,6 @@
- <% if @web_push_subscriptions.any? %> -
-
Devices receiving notifications
-
    - <% @web_push_subscriptions.each do |sub| %> -
  • -
    <%= sub.device_label %>
    -
    - Added <%= time_ago_in_words(sub.created_at) %> ago - <% if sub.last_delivered_at %> - · last notified <%= time_ago_in_words(sub.last_delivered_at) %> ago - · <%= pluralize(sub.notifications_delivered_count, "notification") %> - <% else %> - · no notifications yet - <% end %> -
    -
  • - <% end %> -
-

- To remove a device, sign in to CoPlan from that browser and click "Disable on this device". -

-
- <% end %> + <%= render partial: "coplan/settings/settings/devices", + locals: { web_push_subscriptions: @web_push_subscriptions } %>
diff --git a/engine/config/routes.rb b/engine/config/routes.rb index e7e801e..beabb6e 100644 --- a/engine/config/routes.rb +++ b/engine/config/routes.rb @@ -76,6 +76,10 @@ # PushManager and uniquely identify a (browser, device, app) tuple per user. scope :web_push, module: "web_push", as: :web_push do resource :subscription, only: [:create, :destroy], controller: "subscriptions" + # Turbo-frame target for the per-device list on the Settings page. + # Reloaded by the settings Stimulus controller after enable/disable so + # the list reflects the new browser without a full page refresh. + get "devices", to: "subscriptions#devices", as: :devices end root "plans#index"