Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AshAdmin.Layouts and Phoenix.VerifiedRoutes #68

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 0 additions & 61 deletions lib/ash_admin/components/layouts.ex

This file was deleted.

25 changes: 25 additions & 0 deletions lib/ash_admin/layouts.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule AshAdmin.Layouts do
@moduledoc false
use AshAdmin.Web, :html

embed_templates "layouts/*"

def live_socket_path(conn) do
[Enum.map(conn.script_name, &["/" | &1]) | conn.private.live_socket_path]
end

def asset_hash("/statics/" <> path) do
file =
Application.app_dir(:ash_admin, ["priv", "static", path])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems strange. I've not seen something like this in a phoenix application before, how is it normally done for static assets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what exacly it is stange? the way I am reading the asset or reading the assets to get the md5 hash to append to the url?

Let me give you more context, phoenix application normally manages the asset and cache running the task mix phx.digest, the result for that is an asset minified and zipped with this pattern name asset-#{hash}.#{ext}.gz
But because ash admin is not an application, its assets are not handle for mix phx.digest, we have to do it runtime or manual (digest each asset before release any version)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what feels strange to me is that we're reading a file to hash it to figure out where its minified version is, but we're doing it every time a page load happens. I think it would be better to make this a macro or use a module attribute to store the hash of it at compile time. You can use @external_dependency to cause external files to trigger recompiles.

|> File.read!()

:crypto.hash(:md5, file)
|> Base.encode16(case: :lower)
end

def asset_path(conn, asset) do
hash = asset_hash(asset)

ash_admin_path(conn, "#{asset}?vsn=#{hash}")
end
end
29 changes: 29 additions & 0 deletions lib/ash_admin/layouts/root.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en" phx-socket={live_socket_path(@conn)}>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
/>
<meta name="csrf-token" content={get_csrf_token()} />
<title><%= assigns[:page_title] || "Ash Admin" %></title>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.1/jsoneditor.min.css"
rel="stylesheet"
type="text/css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.1/jsoneditor.min.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/easymde/dist/easymde.min.css"
/>
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<link phx-track-static rel="stylesheet" href={asset_path(@conn, "/statics/assets/app.css")} />
<script defer phx-track-static type="text/javascript" src={asset_path(@conn, "/statics/assets/app.js")} />
</head>
<body>
<%= @inner_content %>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,49 +1,27 @@
defmodule AshAdmin.PageNotFound do
defmodule AshAdmin.ResourceLive.Index do
@moduledoc false
defexception [:message, plug_status: 404]
end

defmodule AshAdmin.PageLive do
@moduledoc false
use Phoenix.LiveView
use AshAdmin.Web, :live_view

import AshAdmin.Helpers
require Ash.Query

alias AshAdmin.Components.{Resource, TopNav}

require Logger

def mount(socket) do
{:ok, socket}
end

@impl true
def mount(
_params,
%{
"prefix" => prefix
} = session,
session,
socket
) do
otp_app = socket.endpoint.config(:otp_app)

prefix =
case prefix do
"/" ->
session["request_path"]

_ ->
request_path = session["request_path"]
[scope, _] = String.split(request_path, prefix)
scope <> prefix
end

socket = assign(socket, :prefix, prefix)

apis = apis(otp_app)

{:ok,
socket
|> assign(:prefix, prefix)
|> assign(:primary_key, nil)
|> assign(:record, nil)
|> assign(:apis, apis)
Expand Down Expand Up @@ -77,7 +55,7 @@ defmodule AshAdmin.PageLive do
toggle_authorizing="toggle_authorizing"
toggle_actor_paused="toggle_actor_paused"
clear_actor="clear_actor"
prefix={@prefix}
prefix={ash_admin_path(@socket, "")}
/>
<.live_component
:if={@resource}
Expand All @@ -99,7 +77,7 @@ defmodule AshAdmin.PageLive do
table={@table}
tables={@tables}
polymorphic_actions={@polymorphic_actions}
prefix={@prefix}
prefix={ash_admin_path(@socket, "")}
/>
"""
end
Expand Down
42 changes: 28 additions & 14 deletions lib/ash_admin/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,34 @@ defmodule AshAdmin.Router do
"""
defmacro ash_admin(path, opts \\ []) do
quote bind_quoted: [path: path, opts: opts] do
import Phoenix.LiveView.Router
live_socket_path = Keyword.get(opts, :live_socket_path, "/live")

live_session :ash_admin,
on_mount: List.wrap(opts[:on_mount]),
session:
{AshAdmin.Router, :__session__, [%{"prefix" => path}, List.wrap(opts[:session])]},
root_layout: {AshAdmin.Layouts, :root} do
live(
"#{path}/*route",
AshAdmin.PageLive,
:page,
private: %{live_socket_path: live_socket_path}
)
scope path, alias: false, as: false do
import Phoenix.LiveView.Router
live_socket_path = Keyword.get(opts, :live_socket_path, "/live")

live_session :ash_admin,
on_mount: List.wrap(opts[:on_mount]),
session:
{AshAdmin.Router, :__session__, [%{"prefix" => path}, List.wrap(opts[:session])]},
root_layout: {AshAdmin.Layouts, :root} do
live "/", AshAdmin.ResourceLive.Index, :index,
private: %{live_socket_path: live_socket_path}

forward "/", Plug.Static,
at: "/statics",
from: :ash_admin,
gzip: false,
only: AshAdmin.Web.static_paths()
end
end

unless Module.get_attribute(__MODULE__, :live_ash_admin_prefix) do
@live_ash_admin_prefix Phoenix.Router.scoped_path(__MODULE__, path)
def __live_ash_admin_prefix__ do
case @live_ash_admin_prefix do
"/" -> ""
path -> path
end
end
end
end
end
Expand Down
50 changes: 26 additions & 24 deletions lib/ash_admin/web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,9 @@ defmodule AshAdmin.Web do
@moduledoc false
def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)

def router do
quote do
use Phoenix.Router, helpers: false

# Import common connection and controller functions to use in pipelines
import Plug.Conn
import Phoenix.Controller
import Phoenix.LiveView.Router
end
end

def channel do
quote do
use Phoenix.Channel
end
end

def live_view do
quote do
use Phoenix.LiveView,
layout: {AshAdmin.Layouts, :app}
use Phoenix.LiveView

unquote(html_helpers())
end
Expand Down Expand Up @@ -61,15 +43,35 @@ defmodule AshAdmin.Web do
alias Phoenix.LiveView.JS

# Routes generation with the ~p sigil
unquote(verified_routes())
unquote(unverified_routes())
end
end

def verified_routes do
defp unverified_routes do
quote do
use Phoenix.VerifiedRoutes,
router: AshAdmin.Router,
statics: AshAdmin.Web.static_paths()
alias Phoenix.LiveView.Socket

def ash_admin_path(conn_or_socket, path, params \\ %{})

def ash_admin_path(%Socket{router: phoenix_router} = socket, path, params) do
prefix = phoenix_router.__live_ash_admin_prefix__()

Phoenix.VerifiedRoutes.unverified_path(
socket,
phoenix_router,
"#{prefix}#{path}",
params
)
end

def ash_admin_path(
%Plug.Conn{private: %{phoenix_router: phoenix_router}} = conn,
path,
params
) do
prefix = phoenix_router.__live_ash_admin_prefix__()
Phoenix.VerifiedRoutes.unverified_path(conn, phoenix_router, "#{prefix}#{path}", params)
end
end
end

Expand Down
2,329 changes: 2,328 additions & 1 deletion priv/static/assets/app.css

Large diffs are not rendered by default.

Loading
Loading