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? %> +
+ To remove a device, sign in to CoPlan from that browser and click "Disable on this device". +
+- To remove a device, sign in to CoPlan from that browser and click "Disable on this device". -
-