82 lines
2.2 KiB
Elixir
82 lines
2.2 KiB
Elixir
|
|
defmodule BerrypodWeb.NavigationController do
|
||
|
|
@moduledoc """
|
||
|
|
No-JS fallback for navigation form submission.
|
||
|
|
|
||
|
|
With JS enabled, the LiveView handles everything. Without JS,
|
||
|
|
the form POSTs here and we redirect back to the LiveView page.
|
||
|
|
"""
|
||
|
|
use BerrypodWeb, :controller
|
||
|
|
|
||
|
|
alias Berrypod.Settings
|
||
|
|
|
||
|
|
def save(conn, %{"header_nav" => header_json, "footer_nav" => footer_json}) do
|
||
|
|
with {:ok, header_items} <- Jason.decode(header_json),
|
||
|
|
{:ok, footer_items} <- Jason.decode(footer_json) do
|
||
|
|
all_items = header_items ++ footer_items
|
||
|
|
errors = validate_nav_items(all_items)
|
||
|
|
|
||
|
|
if errors == [] do
|
||
|
|
Settings.put_setting("header_nav", header_items, "json")
|
||
|
|
Settings.put_setting("footer_nav", footer_items, "json")
|
||
|
|
|
||
|
|
conn
|
||
|
|
|> put_flash(:info, "Navigation saved")
|
||
|
|
|> redirect(to: ~p"/admin/navigation")
|
||
|
|
else
|
||
|
|
conn
|
||
|
|
|> put_flash(:error, Enum.join(errors, ". "))
|
||
|
|
|> redirect(to: ~p"/admin/navigation")
|
||
|
|
end
|
||
|
|
else
|
||
|
|
{:error, _} ->
|
||
|
|
conn
|
||
|
|
|> put_flash(:error, "Invalid navigation data")
|
||
|
|
|> redirect(to: ~p"/admin/navigation")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
defp validate_nav_items(items) do
|
||
|
|
items
|
||
|
|
|> Enum.flat_map(fn item ->
|
||
|
|
cond do
|
||
|
|
item["label"] == "" || item["label"] == nil ->
|
||
|
|
["All links need a label"]
|
||
|
|
|
||
|
|
item["href"] == "" || item["href"] == nil ->
|
||
|
|
["\"#{item["label"]}\" needs a destination"]
|
||
|
|
|
||
|
|
item["external"] == true || is_external_url?(item["href"]) ->
|
||
|
|
if valid_url?(item["href"]) do
|
||
|
|
[]
|
||
|
|
else
|
||
|
|
["\"#{item["label"]}\" has an invalid URL"]
|
||
|
|
end
|
||
|
|
|
||
|
|
true ->
|
||
|
|
[]
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|> Enum.uniq()
|
||
|
|
end
|
||
|
|
|
||
|
|
defp valid_url?(url) when is_binary(url) do
|
||
|
|
case URI.parse(url) do
|
||
|
|
%URI{scheme: scheme, host: host}
|
||
|
|
when scheme in ["http", "https"] and is_binary(host) and host != "" ->
|
||
|
|
true
|
||
|
|
|
||
|
|
_ ->
|
||
|
|
false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
defp valid_url?(_), do: false
|
||
|
|
|
||
|
|
defp is_external_url?(nil), do: false
|
||
|
|
defp is_external_url?(""), do: false
|
||
|
|
|
||
|
|
defp is_external_url?(href) do
|
||
|
|
String.starts_with?(href, "http://") || String.starts_with?(href, "https://")
|
||
|
|
end
|
||
|
|
end
|