Skip to content

Commit

Permalink
update phoenix & live_view
Browse files Browse the repository at this point in the history
  • Loading branch information
sorax committed Dec 9, 2024
1 parent 5c041d9 commit 638846e
Show file tree
Hide file tree
Showing 17 changed files with 185 additions and 136 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ radiator-*.tar
npm-debug.log
/assets/node_modules/

.lexical
3 changes: 0 additions & 3 deletions .iex.exs

This file was deleted.

50 changes: 50 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,56 @@ if config_env() == :prod do
],
secret_key_base: secret_key_base

# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
# to your endpoint configuration:
#
# config :radiator, RadiatorWeb.Endpoint,
# https: [
# ...,
# port: 443,
# cipher_suite: :strong,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
# ]
#
# The `cipher_suite` is set to `:strong` to support only the
# latest and more secure SSL ciphers. This means old browsers
# and clients may not be supported. You can set it to
# `:compatible` for wider support.
#
# `:keyfile` and `:certfile` expect an absolute path to the key
# and cert in disk or a relative path inside priv, for example
# "priv/ssl/server.key". For all supported SSL configuration
# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
#
# We also recommend setting `force_ssl` in your config/prod.exs,
# ensuring no data is ever sent via http, always redirecting to https:
#
# config :radiator, RadiatorWeb.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.

# ## Configuring the mailer
#
# In production you need to configure the mailer to use a different adapter.
# Also, you may need to configure the Swoosh API client of your choice if you
# are not using SMTP. Here is an example of the configuration:
#
# config :radiator, Radiator.Mailer,
# adapter: Swoosh.Adapters.Mailgun,
# api_key: System.get_env("MAILGUN_API_KEY"),
# domain: System.get_env("MAILGUN_DOMAIN")
#
# For this example you need include a HTTP client required by Swoosh API client.
# Swoosh supports Hackney and Finch out of the box:
#
# config :swoosh, :api_client, Swoosh.ApiClient.Hackney
#
# See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.

config :radiator, Radiator.Mailer,
adapter: Swoosh.Adapters.SMTP,
relay: System.get_env("SMTP_SERVER"),
Expand Down
4 changes: 2 additions & 2 deletions lib/radiator_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ defmodule RadiatorWeb do
layouts: [html: RadiatorWeb.Layouts]

import Plug.Conn
use Gettext, backend: RadiatorWeb.Gettext
import RadiatorWeb.Gettext

unquote(verified_routes())
end
Expand Down Expand Up @@ -88,7 +88,7 @@ defmodule RadiatorWeb do

# Core UI components and translation
import RadiatorWeb.CoreComponents
use Gettext, backend: RadiatorWeb.Gettext
import RadiatorWeb.Gettext

# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
Expand Down
93 changes: 47 additions & 46 deletions lib/radiator_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ defmodule RadiatorWeb.CoreComponents do
Icons are provided by [heroicons](https://heroicons.com). See `icon/1` for usage.
"""
use Phoenix.Component
use Gettext, backend: RadiatorWeb.Gettext

alias Phoenix.HTML
import RadiatorWeb.Gettext

alias Phoenix.HTML.Form
alias Phoenix.HTML.FormField
alias Phoenix.LiveView.JS

@doc """
Expand Down Expand Up @@ -80,7 +82,7 @@ defmodule RadiatorWeb.CoreComponents do
</button>
</div>
<div id={"#{@id}-content"}>
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</div>
</.focus_wrap>
</div>
Expand Down Expand Up @@ -125,9 +127,9 @@ defmodule RadiatorWeb.CoreComponents do
<p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
<.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
<.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
<%= @title %>
{@title}
</p>
<p class="mt-2 text-sm leading-5"><%= msg %></p>
<p class="mt-2 text-sm leading-5">{msg}</p>
<button type="button" class="group absolute top-1 right-1 p-2" aria-label={gettext("close")}>
<.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" />
</button>
Expand Down Expand Up @@ -158,7 +160,7 @@ defmodule RadiatorWeb.CoreComponents do
phx-connected={hide("#client-error")}
hidden
>
<%= gettext("Attempting to reconnect") %>
{gettext("Attempting to reconnect")}
<.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" />
</.flash>
Expand All @@ -170,7 +172,7 @@ defmodule RadiatorWeb.CoreComponents do
phx-connected={hide("#server-error")}
hidden
>
<%= gettext("Hang in there while we get back on track") %>
{gettext("Hang in there while we get back on track")}
<.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" />
</.flash>
</div>
Expand Down Expand Up @@ -204,9 +206,9 @@ defmodule RadiatorWeb.CoreComponents do
~H"""
<.form :let={f} for={@for} as={@as} {@rest}>
<div class="mt-10 space-y-8 bg-white">
<%= render_slot(@inner_block, f) %>
{render_slot(@inner_block, f)}
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
<%= render_slot(action, f) %>
{render_slot(action, f)}
</div>
</div>
</.form>
Expand Down Expand Up @@ -238,7 +240,7 @@ defmodule RadiatorWeb.CoreComponents do
]}
{@rest}
>
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</button>
"""
end
Expand Down Expand Up @@ -279,21 +281,20 @@ defmodule RadiatorWeb.CoreComponents do
values: ~w(checkbox color date datetime-local email file month number password
range search select tel text textarea time url week)

attr :field, HTML.FormField,
attr :field, FormField,
doc: "a form field struct retrieved from the form, for example: @form[:email]"

attr :errors, :list, default: []
attr :checked, :boolean, doc: "the checked flag for checkbox inputs"
attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
attr :class, :string, default: nil

attr :rest, :global,
include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
multiple pattern placeholder readonly required rows size step)

def input(%{field: %HTML.FormField{} = field} = assigns) do
def input(%{field: %FormField{} = field} = assigns) do
errors = if Phoenix.Component.used_input?(field), do: field.errors, else: []

assigns
Expand All @@ -307,11 +308,11 @@ defmodule RadiatorWeb.CoreComponents do
def input(%{type: "checkbox"} = assigns) do
assigns =
assign_new(assigns, :checked, fn ->
HTML.Form.normalize_value("checkbox", assigns[:value])
Form.normalize_value("checkbox", assigns[:value])
end)

~H"""
<div class={@class}>
<div>
<label class="flex items-center gap-4 text-sm leading-6 text-zinc-600">
<input type="hidden" name={@name} value="false" disabled={@rest[:disabled]} />
<input
Expand All @@ -323,36 +324,36 @@ defmodule RadiatorWeb.CoreComponents do
class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
{@rest}
/>
<%= @label %>
{@label}
</label>
<.error :for={msg <- @errors}><%= msg %></.error>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end

def input(%{type: "select"} = assigns) do
~H"""
<div class={@class}>
<.label for={@id}><%= @label %></.label>
<div>
<.label for={@id}>{@label}</.label>
<select
id={@id}
name={@name}
class="mt-2 block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
multiple={@multiple}
{@rest}
>
<option :if={@prompt} value=""><%= @prompt %></option>
<%= HTML.Form.options_for_select(@options, @value) %>
<option :if={@prompt} value="">{@prompt}</option>
{Form.options_for_select(@options, @value)}
</select>
<.error :for={msg <- @errors}><%= msg %></.error>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end

def input(%{type: "textarea"} = assigns) do
~H"""
<div class={@class}>
<.label for={@id}><%= @label %></.label>
<div>
<.label for={@id}>{@label}</.label>
<textarea
id={@id}
name={@name}
Expand All @@ -362,30 +363,30 @@ defmodule RadiatorWeb.CoreComponents do
@errors != [] && "border-rose-400 focus:border-rose-400"
]}
{@rest}
><%= HTML.Form.normalize_value("textarea", @value) %></textarea>
<.error :for={msg <- @errors}><%= msg %></.error>
>{Form.normalize_value("textarea", @value)}</textarea>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end

# All other inputs text, datetime-local, url, password, etc. are handled here...
def input(assigns) do
~H"""
<div class={@class}>
<.label for={@id}><%= @label %></.label>
<div>
<.label for={@id}>{@label}</.label>
<input
type={@type}
name={@name}
id={@id}
value={HTML.Form.normalize_value(@type, @value)}
value={Form.normalize_value(@type, @value)}
class={[
"mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6",
@errors == [] && "border-zinc-300 focus:border-zinc-400",
@errors != [] && "border-rose-400 focus:border-rose-400"
]}
{@rest}
/>
<.error :for={msg <- @errors}><%= msg %></.error>
<.error :for={msg <- @errors}>{msg}</.error>
</div>
"""
end
Expand All @@ -399,7 +400,7 @@ defmodule RadiatorWeb.CoreComponents do
def label(assigns) do
~H"""
<label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800">
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</label>
"""
end
Expand All @@ -413,7 +414,7 @@ defmodule RadiatorWeb.CoreComponents do
~H"""
<p class="mt-3 flex gap-3 text-sm leading-6 text-rose-600">
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</p>
"""
end
Expand All @@ -432,13 +433,13 @@ defmodule RadiatorWeb.CoreComponents do
<header class={[@actions != [] && "flex items-center justify-between gap-6", @class]}>
<div>
<h1 class="text-lg font-semibold leading-8 text-zinc-800">
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</h1>
<p :if={@subtitle != []} class="mt-2 text-sm leading-6 text-zinc-600">
<%= render_slot(@subtitle) %>
{render_slot(@subtitle)}
</p>
</div>
<div class="flex-none"><%= render_slot(@actions) %></div>
<div class="flex-none">{render_slot(@actions)}</div>
</header>
"""
end
Expand All @@ -449,8 +450,8 @@ defmodule RadiatorWeb.CoreComponents do
## Examples
<.table id="users" rows={@users}>
<:col :let={user} label="id"><%= user.id %></:col>
<:col :let={user} label="username"><%= user.username %></:col>
<:col :let={user} label="id">{user.id}</:col>
<:col :let={user} label="username">{user.username}</:col>
</.table>
"""
attr :id, :string, required: true
Expand Down Expand Up @@ -479,9 +480,9 @@ defmodule RadiatorWeb.CoreComponents do
<table class="w-[40rem] mt-11 sm:w-full">
<thead class="text-sm text-left leading-6 text-zinc-500">
<tr>
<th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal"><%= col[:label] %></th>
<th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal">{col[:label]}</th>
<th :if={@action != []} class="relative p-0 pb-4">
<span class="sr-only"><%= gettext("Actions") %></span>
<span class="sr-only">{gettext("Actions")}</span>
</th>
</tr>
</thead>
Expand All @@ -499,7 +500,7 @@ defmodule RadiatorWeb.CoreComponents do
<div class="block py-4 pr-6">
<span class="absolute -inset-y-px right-0 -left-4 group-hover:bg-zinc-50 sm:rounded-l-xl" />
<span class={["relative", i == 0 && "font-semibold text-zinc-900"]}>
<%= render_slot(col, @row_item.(row)) %>
{render_slot(col, @row_item.(row))}
</span>
</div>
</td>
Expand All @@ -510,7 +511,7 @@ defmodule RadiatorWeb.CoreComponents do
:for={action <- @action}
class="relative ml-4 font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
>
<%= render_slot(action, @row_item.(row)) %>
{render_slot(action, @row_item.(row))}
</span>
</div>
</td>
Expand All @@ -527,8 +528,8 @@ defmodule RadiatorWeb.CoreComponents do
## Examples
<.list>
<:item title="Title"><%= @post.title %></:item>
<:item title="Views"><%= @post.views %></:item>
<:item title="Title">{@post.title}</:item>
<:item title="Views">{@post.views}</:item>
</.list>
"""
slot :item, required: true do
Expand All @@ -540,8 +541,8 @@ defmodule RadiatorWeb.CoreComponents do
<div class="mt-14">
<dl class="-my-4 divide-y divide-zinc-100">
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt>
<dd class="text-zinc-700"><%= render_slot(item) %></dd>
<dt class="w-1/4 flex-none text-zinc-500">{item.title}</dt>
<dd class="text-zinc-700">{render_slot(item)}</dd>
</div>
</dl>
</div>
Expand All @@ -566,7 +567,7 @@ defmodule RadiatorWeb.CoreComponents do
class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
>
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
<%= render_slot(@inner_block) %>
{render_slot(@inner_block)}
</.link>
</div>
"""
Expand Down
Loading

0 comments on commit 638846e

Please sign in to comment.