Skip to content

Commit

Permalink
Merge branch 'main' into lp-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
leandrocp committed Dec 20, 2024
2 parents 75673d6 + 681ad3e commit 2fe0bbd
Show file tree
Hide file tree
Showing 16 changed files with 147 additions and 138 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

## 0.3.3 (2024-12-13)

### Fixes

- Support LiveView v1.0.1
- Fix variant roll changing when fetching assets

## 0.3.2 (2024-12-11)

### Fixes
Expand Down
4 changes: 2 additions & 2 deletions assets/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion assets/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "beacon",
"version": "0.3.2",
"version": "0.3.3",
"license": "MIT",
"repository": {},
"scripts": {
Expand Down
25 changes: 24 additions & 1 deletion lib/beacon/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,32 @@ defmodule Beacon.Plug do
"""
@behaviour Plug

@private_routes [
"__beacon_check__",
"__beacon_assets__",
"__beacon_media__"
]

@impl Plug
def init(_opts), do: []

@impl Plug
def call(conn, _opts), do: Plug.Conn.put_session(conn, :beacon_variant_roll, Enum.random(1..100))
def call(conn, _opts) do
if Enum.any?(@private_routes, &(&1 in conn.path_info)) do
conn
else
put_roll(conn)
end
end

defp put_roll(conn) do
path_list = conn.path_params["path"]

with %{private: %{phoenix_live_view: {_, _, %{extra: %{session: %{"beacon_site" => site}}}}}} <- conn,
{_, _} <- Beacon.RouterServer.lookup_path(site, path_list, 1) do
Plug.Conn.put_session(conn, "beacon_variant_roll", Enum.random(1..100))
else
_ -> conn
end
end
end
14 changes: 13 additions & 1 deletion lib/beacon/private.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ defmodule Beacon.Private do

# Should be avoided as much as possible.

@phoenix_live_view_version to_string(Application.spec(:phoenix_live_view)[:vsn])

@doc """
On page navigation, the request might actually hit a different site than the one defined by the current session.
Expand All @@ -20,7 +22,7 @@ defmodule Beacon.Private do
We use the private function `Phoenix.LiveView.Route.live_link_info/3` in order to keep the same behavior as LV.
"""
def site_from_session(endpoint, router, url, view) do
case Phoenix.LiveView.Route.live_link_info(endpoint, router, url) do
case live_link_info(endpoint, router, url) do
{_,
%{
view: ^view,
Expand All @@ -36,4 +38,14 @@ defmodule Beacon.Private do
nil
end
end

if Version.compare(@phoenix_live_view_version, "1.0.0") == :gt do
defp live_link_info(endpoint, router, url) do
Phoenix.LiveView.Route.live_link_info_without_checks(endpoint, router, url)
end
else
defp live_link_info(endpoint, router, url) do
Phoenix.LiveView.Route.live_link_info(endpoint, router, url)
end
end
end
2 changes: 2 additions & 0 deletions lib/beacon/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ defmodule Beacon.Router do
end)
end

def path_params(_page_path, _path_info), do: %{}

@doc false
# Tells if a `beacon_site` is reachable in the current environment.
#
Expand Down
4 changes: 2 additions & 2 deletions lib/beacon/template.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ defmodule Beacon.Template do

page ->
page_module = Beacon.Loader.fetch_page_module(page.site, page.id)
live_data = Beacon.Web.DataSource.live_data(site, path_info)
beacon_assigns = BeaconAssigns.new(site, page, live_data, path_info, query_params, :beacon)
live_data = Beacon.Web.DataSource.live_data(site, path_info, query_params)
beacon_assigns = BeaconAssigns.new(page, path_info: path_info, query_params: query_params)
assigns = Map.put(live_data, :beacon, beacon_assigns)
env = Beacon.Web.PageLive.make_env(site)

Expand Down
56 changes: 12 additions & 44 deletions lib/beacon/web/beacon_assigns.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ defmodule Beacon.Web.BeaconAssigns do
}

defstruct site: nil,
path_params: %{},
query_params: %{},
path_params: nil,
query_params: nil,
page: %{path: nil, title: nil},
private: %{
page_module: nil,
Expand All @@ -53,31 +53,18 @@ defmodule Beacon.Web.BeaconAssigns do
end

@doc false
def new(site, %Beacon.Content.Page{} = page, variant_roll) do
components_module = Beacon.Loader.Components.module_name(site)
page_module = Beacon.Loader.Page.module_name(site, page.id)
def new(%Beacon.Content.Page{} = page, metadata \\ []) do
path_info = Keyword.get(metadata, :path_info, [])
query_params = Keyword.get(metadata, :query_params, %{})
variant_roll = Keyword.get(metadata, :variant_roll, nil)

%__MODULE__{
site: site,
private: %{
components_module: components_module,
page_module: page_module,
variant_roll: variant_roll
}
}
end

@doc false
def new(site, %Beacon.Content.Page{} = page, live_data, path_info, query_params, source, variant_roll \\ nil)
when is_atom(site) and is_map(live_data) and is_list(path_info) and is_map(query_params) and source in [:beacon, :admin] do
%{site: ^site} = page
page_module = Beacon.Loader.Page.module_name(site, page.id)
live_data = Beacon.Web.DataSource.live_data(site, path_info, Map.drop(query_params, ["path"]))
page_module = Beacon.Loader.Page.module_name(page.site, page.id)
live_data = Beacon.Web.DataSource.live_data(page.site, path_info, Map.drop(query_params, ["path"]))
path_params = Beacon.Router.path_params(page.path, path_info)
page_title = Beacon.Web.DataSource.page_title(site, page.id, live_data, source)
components_module = Beacon.Loader.Components.module_name(site)
info_handlers_module = Beacon.Loader.InfoHandlers.module_name(site)
event_handlers_module = Beacon.Loader.EventHandlers.module_name(site)
page_title = Beacon.Web.DataSource.page_title(page, live_data)
components_module = Beacon.Loader.Components.module_name(page.site)
info_handlers_module = Beacon.Loader.InfoHandlers.module_name(page.site)
event_handlers_module = Beacon.Loader.EventHandlers.module_name(page.site)

%__MODULE__{
site: page.site,
Expand All @@ -95,23 +82,4 @@ defmodule Beacon.Web.BeaconAssigns do
}
}
end

@doc false
def update(_socket_or_assigns, _key, _value)

def update(%{assigns: %{beacon: _beacon}} = socket, key, value) do
do_update_socket_or_assigns(socket, key, value)
end

def update(%{beacon: _beacon} = assigns, key, value) do
do_update_socket_or_assigns(assigns, key, value)
end

def update(_socket_or_assigns, _key, _value), do: raise("expected :beacon assign in socket but none found")

defp do_update_socket_or_assigns(socket_or_assigns, key, value) do
Phoenix.Component.update(socket_or_assigns, :beacon, fn beacon ->
Map.put(beacon, key, value)
end)
end
end
2 changes: 1 addition & 1 deletion lib/beacon/web/controllers/api/page_json.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Beacon.Web.API.PageJSON do
defp data(%Page{} = page) do
path_info = for segment <- String.split(page.path, "/"), segment != "", do: segment
live_data = Beacon.Web.DataSource.live_data(page.site, path_info, %{})
beacon_assigns = BeaconAssigns.new(page.site, page, live_data, path_info, %{}, :admin)
beacon_assigns = BeaconAssigns.new(page, path_info: path_info)

assigns =
live_data
Expand Down
35 changes: 22 additions & 13 deletions lib/beacon/web/data_source.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ defmodule Beacon.Web.DataSource do

require Logger

def live_data(site, path_info, params \\ %{}) when is_atom(site) and is_list(path_info) and is_map(params) do
Beacon.apply_mfa(site, Beacon.Loader.fetch_live_data_module(site), :live_data, [path_info, params])
def live_data(site, path_info, query_params) when is_atom(site) and is_list(path_info) and is_map(query_params) do
Beacon.apply_mfa(site, Beacon.Loader.fetch_live_data_module(site), :live_data, [path_info, query_params])
end

def page_title(site, page_id, live_data, source) do
%{path: path, title: title} = page_assigns = page_assigns(site, page_id, source)
def live_data(_site, _path_info, _query_params), do: %{}

def page_title(%Beacon.Content.Page{} = page, live_data) do
%{path: path, title: title} = page_assigns = page_assigns(page)

with {:ok, page_title} <- Beacon.Content.render_snippet(title, %{page: page_assigns, live_data: live_data}) do
page_title
Expand All @@ -19,7 +21,7 @@ defmodule Beacon.Web.DataSource do
will return the original unmodified page title
site: #{site}
site: #{page.site}
title: #{title}
page path: #{path}
Expand All @@ -36,13 +38,14 @@ defmodule Beacon.Web.DataSource do
# TODO: revisit this logic to evaluate meta_tags for unpublished pages
def meta_tags(assigns) do
%{beacon: %{site: site, private: %{page_module: page_module, live_data_keys: live_data_keys}}} = assigns
%{site: ^site, id: page_id} = Beacon.apply_mfa(site, page_module, :page_assigns, [[:site, :id]])
%{site: ^site} = page_assigns = Beacon.apply_mfa(site, page_module, :page_assigns, [])

live_data = Map.take(assigns, live_data_keys)

assigns
|> Beacon.Web.Layouts.meta_tags()
|> List.wrap()
|> Enum.map(&interpolate_meta_tag(&1, %{page: page_assigns(site, page_id, :beacon), live_data: live_data}))
|> Enum.map(&interpolate_meta_tag(&1, %{page: page_assigns, live_data: live_data}))
end

defp interpolate_meta_tag(meta_tag, values) when is_map(meta_tag) do
Expand All @@ -57,15 +60,21 @@ defmodule Beacon.Web.DataSource do
end
end

# only published pages will have the title evaluated for beacon
defp page_assigns(site, page_id, :beacon) do
Beacon.apply_mfa(site, Beacon.Loader.fetch_page_module(site, page_id), :page_assigns, [])
# return the page assigns from unpublished page assigns,
# either saved in the database or page in-memory (for new pages)
# this fallback is here mostly to support beacon_live_admin visual editor,
# which makes use of the `@beacon` assign when creating or editing pages
defp page_assigns(%Beacon.Content.Page{id: nil} = page) do
unpublished_page_assigns(page)
end

# beacon_live_admin needs the title for unpublished pages also
defp page_assigns(site, page_id, :admin) do
page = Beacon.Content.get_page(site, page_id)
defp page_assigns(%Beacon.Content.Page{} = page) do
Beacon.apply_mfa(page.site, Beacon.Loader.fetch_page_module(page.site, page.id), :page_assigns, [])
rescue
_ -> unpublished_page_assigns(page)
end

defp unpublished_page_assigns(page) do
%{
id: page.id,
site: page.site,
Expand Down
14 changes: 6 additions & 8 deletions lib/beacon/web/live/page_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule Beacon.Web.PageLive do
end

page = RouterServer.lookup_page!(site, path)
socket = Component.assign(socket, beacon: BeaconAssigns.new(site, page, variant_roll))
socket = Component.assign(socket, beacon: BeaconAssigns.new(page, variant_roll: variant_roll))

{:ok, socket, layout: {Beacon.Web.Layouts, :dynamic}}
end
Expand Down Expand Up @@ -130,16 +130,14 @@ defmodule Beacon.Web.PageLive do
site ->
%{"path" => path_info} = params

if socket.assigns.beacon.site != site do
if Beacon.Config.fetch!(site).mode == :live do
Beacon.PubSub.unsubscribe_to_page(socket.assigns.beacon.site, path_info)
Beacon.PubSub.subscribe_to_page(site, path_info)
end
if socket.assigns.beacon.site != site && Beacon.Config.fetch!(site).mode == :live do
Beacon.PubSub.unsubscribe_to_page(socket.assigns.beacon.site, path_info)
Beacon.PubSub.subscribe_to_page(site, path_info)
end

page = RouterServer.lookup_page!(site, path_info)
live_data = Beacon.Web.DataSource.live_data(site, path_info, Map.drop(params, ["path"]))
beacon_assigns = BeaconAssigns.new(site, page, live_data, path_info, params, :beacon, socket.assigns.beacon.private.variant_roll)
beacon_assigns = BeaconAssigns.new(page, path_info: path_info, query_params: params, variant_roll: socket.assigns.beacon.private.variant_roll)

socket =
socket
Expand All @@ -151,7 +149,7 @@ defmodule Beacon.Web.PageLive do
# TODO: remove deprecated @beacon_query_params
|> Component.assign(:beacon_query_params, beacon_assigns.query_params)
|> Component.assign(:beacon, beacon_assigns)
|> Component.assign(:page_title, Beacon.Web.DataSource.page_title(site, page.id, live_data, :beacon))
|> Component.assign(:page_title, beacon_assigns.page.title)

{:noreply, push_event(socket, "beacon:page-updated", %{meta_tags: Beacon.Web.DataSource.meta_tags(socket.assigns)})}
end
Expand Down
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Beacon.MixProject do
use Mix.Project

@version "0.3.2"
@version "0.3.3"
@source_url "https://github.com/BeaconCMS/beacon"
@homepage_url "https://beaconcms.org"

Expand Down Expand Up @@ -70,7 +70,7 @@ defmodule Beacon.MixProject do
{:image, "~> 0.40"},
{:vix, "<= 0.30.0 or >= 0.31.1"},
{:jason, "~> 1.0"},
{:oembed, "~> 0.4.1"},
{:oembed, "~> 0.4"},
{:phoenix_ecto, "~> 4.4"},
{:phoenix_html, "~> 4.0"},
{:phoenix_html_helpers, "~> 1.0"},
Expand Down
Loading

0 comments on commit 2fe0bbd

Please sign in to comment.