Move subscription settings page content into a LiveView#6170
Move subscription settings page content into a LiveView#6170
Conversation
Prepares the page to host the choose_plan modal as a LiveComponent in a follow-up PR. Pure refactor, no UX changes. - Extract subscription page content into a new SubscriptionSettings LiveView - Move data loading out of the controller and into the LiveView - Embed the LiveView in the existing settings layout via live_render
ukutaht
left a comment
There was a problem hiding this comment.
Looks good, just a couple comments
- Render SubscriptionSettings LiveView directly from the router instead of via a controller action and template - Update the shared settings layout to work without a request object - Move view helpers from SettingsView to the billing components module
eabfad4 to
11ad786
Compare
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
499427c to
73ab60f
Compare
- Move billing helpers to a dedicated Helpers module - Add a CurrentPath plug to the settings pipeline so we can avoid all the branching in the layout template - Remove conn dependency from the settings layout
73ab60f to
2c9f483
Compare
| |> assign(:team_member_usage, team_member_usage) | ||
| |> assign(:notification_type, notification_type) | ||
| |> assign(:total_pageview_usage_domain, total_pageview_usage_domain) | ||
| |> assign(:current_path, "settings/billing/subscription") |
There was a problem hiding this comment.
This assign should be no longer needed - plug should provide it in the context already 😄
There was a problem hiding this comment.
Tried removing it but it breaks; the plug runs on the HTTP request, but the LiveView uses a WebSocket which doesn't inherit it.
There was a problem hiding this comment.
Okay, my wrong, for some reason I started thinking assigns from conn carry over to LV, which obviously is not the case argh. There will be more LVs, for each setting screen, I presume. We can still make something executed commonly for all LVs though. There's a mechanism for that, similar to plugs but specifically for LV: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#on_mount/1
Ideally, we'd wrap this and all future LV routes for settings in something like this:
live_session :settings, on_mount: PlausibleWeb.Live.SettingsContext do
scope alias: Live, assigns: %{connect_live_socket: true} do
live "/billing/subscription", SubscriptionSettings, :subscription, as: :settings
end
endhttps://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Router.html#live_session/3 brings a number of additional benefits:
settingslayout is consistently applied, so we can skip setting it in every LV'smount(more on that below)- navigating between settings LVs can be potentially made more seamless by using
navigateredirects which avoid full page reloads
I'm not sure if scope alias will work in this case - you might need to provide a full module path in live path definition, like PlausibleWeb.Live.SubscriptionSettings, but maybe not.
As for the context hook module, it's unfortunately tad more hairy than plug because we have to extract URI and need a lifecycle hook for that:
defmodule PlausibleWeb.Live.SettingsContext do
import Phoenix.LiveView
def on_mount(_arg, _params, _session, socket) do
socket = attach_hook(socket, :get_current_path, :handle_params, &get_current_path/3)
{:cont, socket, layout: {PlausibleWeb.Layouts, :settings}}
end
defp get_current_path(_params, url, socket) do
%{path: request_path} = URI.parse(url)
{:cont, assign(socket, :current_path, current_path}
end
endThe above handles both, setting the layout and setting the current_path and potentially other assigns that might be shared in the context of settings LVs.
NOTE: I have not tested that code. If you stumble upon any issues implementing it and get stuck, please shout and we can try to sort this out.
- Use `conn.request_path` instead of `Path.join` in CurrentPath plug
- Remove unused `%Plug.Conn{}` clause from `account_settings_sidebar`
- Use dot notation for always-present assigns in `account_settings_sidebar`
| current_team = assigns.current_team | ||
| current_team_role = assigns.current_team_role |
There was a problem hiding this comment.
These assigns are indeed always set if AuthPlug is present in the pipeline - we just need to keep in mind that they both might be nil. But we should be good here 👍
Changes
Prepares the page to host the choose_plan modal as a LiveComponent in a follow-up PR. Pure refactor, no UX changes.
Tests
Changelog
Documentation
Dark mode