defmodule BerrypodWeb.ErrorHTML do
@moduledoc """
This module is invoked by your endpoint in case of errors on HTML requests.
See config/config.exs.
"""
use BerrypodWeb, :html
alias Berrypod.Pages
alias Berrypod.Pages.Defaults
alias Berrypod.Settings
alias Berrypod.Settings.ThemeSettings
alias Berrypod.Media
alias Berrypod.Products
alias Berrypod.Theme.{CSSCache, CSSGenerator}
def render("404.html", assigns) do
render_error_page(
assigns,
"404",
"Page not found",
"Sorry, we couldn't find the page you're looking for."
)
end
def render("500.html", assigns) do
render_error_page(
assigns,
"500",
"Server error",
"Something went wrong on our end. Please try again later."
)
end
def render("429.html", assigns) do
# 429 gets a bare themed page - just the message, no nav/footer/hero
render_bare_error(assigns, "429", "Too many requests", "Please wait a moment and try again.")
end
def render(template, _assigns) do
Phoenix.Controller.status_message_from_template(template)
end
defp render_error_page(assigns, error_code, error_title, error_description) do
site_live = safe_load(&Settings.site_live?/0) || false
assigns =
assigns
|> Map.put(:error_code, error_code)
|> Map.put(:error_title, error_title)
|> Map.put(:error_description, error_description)
|> Map.put(:site_live, site_live)
if site_live do
render_themed_error(assigns)
else
render_minimal_error(assigns)
end
end
defp render_bare_error(assigns, error_code, error_title, error_description) do
{theme_settings, generated_css} = load_theme_data()
assigns =
assigns
|> Map.put(:error_code, error_code)
|> Map.put(:error_title, error_title)
|> Map.put(:error_description, error_description)
|> Map.put(:theme_settings, theme_settings)
|> Map.put(:generated_css, generated_css)
~H"""
{@error_code} - {@error_title}
{@error_code}
{@error_title}
{@error_description}
"""
end
defp render_minimal_error(assigns) do
~H"""
{@error_code} - {@error_title}
"""
end
defp load_theme_data do
try do
theme_settings = Settings.get_theme_settings()
generated_css =
case CSSCache.get() do
{:ok, css} ->
css
:miss ->
css = CSSGenerator.generate(theme_settings, &BerrypodWeb.Endpoint.static_path/1)
CSSCache.put(css)
css
end
{theme_settings, generated_css}
rescue
_ -> {%ThemeSettings{}, ""}
end
end
defp safe_load(fun) do
try do
fun.()
rescue
_ -> nil
end
end
# Load nav items from database, falling back to defaults if DB fails
# (error pages might render when database is unavailable)
defp load_nav_items(location) do
case safe_load(fn -> Berrypod.Site.nav_items_for_shop(location) end) do
items when is_list(items) and items != [] -> items
_ -> default_nav_items(location)
end
end
defp default_nav_items("header"), do: Berrypod.Site.default_header_nav()
defp default_nav_items("footer"), do: Berrypod.Site.default_footer_nav()
end