Current section
Files
Jump to
Current section
Files
lib/imagine/cms_templates/render_view_helpers.ex
defmodule Imagine.CmsTemplates.RenderViewHelpers do
@moduledoc """
Defines CMS template helpers like text_editor in View mode (i.e. the rendered output)
"""
use Phoenix.HTML
alias Imagine.CmsPages
alias Imagine.CmsPages.{CmsPage, CmsPageObject}
# alias Imagine.CmsTemplates
alias Imagine.CmsTemplates.CmsTemplate
alias Imagine.Repo
# add shortened, @conn-free versions of all the helpers to make templates look nicer
defmacro text_editor(obj_name, opts \\ []) when is_binary(obj_name) do
quote do
text_editor(var!(assigns)[:conn], unquote(obj_name), unquote(opts))
end
end
defmacro snippet(obj_name, opts \\ []) when is_binary(obj_name) do
quote do
snippet(var!(assigns)[:conn], unquote(obj_name), unquote(opts))
end
end
defmacro page_list(obj_name, opts \\ []) when is_binary(obj_name) do
quote do
page_list(var!(assigns)[:conn], unquote(obj_name), unquote(opts))
end
end
def text_editor(%Plug.Conn{assigns: %{cms_page: cms_page}}, obj_name, _opts) do
obj =
cms_page
|> CmsPageObject.extract_page_objects_from_page()
|> CmsPageObject.find_object(obj_name, "text")
case obj do
nil -> nil
_ -> raw(obj.content)
end
end
# def text_editor(_conn, _, _) do
# {:safe,
# "text_editor(): Invalid arguments provided. First argument should be @conn. Second argument should be a name."}
# end
def snippet(%Plug.Conn{} = conn, obj_name, _opts) do
cms_page = conn.assigns[:cms_page] || %CmsPage{}
snippet = Imagine.CmsTemplates.get_cms_snippet_by_name(obj_name)
case snippet do
nil -> "Could not find snippet \"#{obj_name}\" in the database."
_ -> CmsTemplate.render(:edit, snippet.content_eex, cms_page, conn)
end
end
def sort_pages(pages, key1, :asc) do
Enum.sort(pages, &cmp_asc(&1, &2, key1))
end
def sort_pages(pages, key1, :desc) do
Enum.sort(pages, &cmp_desc(&1, &2, key1))
end
# def sort_pages(pages, key1, key1dir, key2, key2dir) do
# Enum.sort(pages, &cmp_asc(&1, &2, key1))
# end
def cmp_eq(a, b, key) when is_binary(key), do: cmp_eq(a, b, String.to_existing_atom(key))
def cmp_eq(a, b, key) do
Map.get(a, key) == Map.get(b, key)
end
def cmp_asc(a, b, key) do
Map.get(a, key) <= Map.get(b, key)
end
def cmp_desc(a, b, key) do
Map.get(b, key) <= Map.get(a, key)
end
def page_list(%Plug.Conn{assigns: %{cms_page: cms_page}}, obj_name, opts) do
pages = gather_pages_from_folders(opts[:folders])
# TODO: combine with pages from tags
pages =
sort_pages(
pages,
opts[:primary_sort_key] || :article_date,
opts[:primary_sort_direction] || :desc
)
output = render_page_list(pages, cms_page, opts)
id = "PageList-#{obj_name}-container"
class = "Imagine-CmsPageObject-PageList"
content_tag :div, id: id, class: class do
raw(output)
end
end
def render_page_list(pages, containing_page, opts) do
[
hbrender(opts[:header], containing_page),
render_page_list_pages(pages, containing_page, opts),
hbrender(opts[:footer], containing_page)
]
end
def hbrender(nil, _context), do: ""
def hbrender(content, context) do
NodeJS.call!("hbrender", [content, context], binary: true)
end
def render_page_list_pages(cms_pages, containing_page, opts, index \\ 1)
def render_page_list_pages([], _containing_page, _opts, _index), do: []
def render_page_list_pages([cms_page | cms_pages], containing_page, opts, index) do
context =
cms_page
|> Map.put(:containing_page, containing_page)
|> Map.put(:index, index)
# NOTE: the Jason encoder ultimately determines which attributes are exposed to hbrender
output = hbrender(opts[:template], context)
[output, render_page_list_pages(cms_pages, containing_page, opts, index + 1)]
end
def gather_pages_from_folders(folders) when is_binary(folders) do
gather_pages_from_folders(folders |> String.split(",") |> Enum.map(&String.trim/1))
end
def gather_pages_from_folders(nil), do: []
def gather_pages_from_folders([]), do: []
def gather_pages_from_folders([folder | folders]) do
cms_page =
folder
|> CmsPages.get_cms_page_by_path()
|> Repo.preload(:sub_pages)
sub_pages =
case cms_page do
# can be nil when page list is pointed at a non-existent path
nil -> []
_ -> cms_page.sub_pages
end
sub_pages ++ gather_pages_from_folders(folders)
end
def template_option(_opt_name, :string) do
"template_option(opt_name, :string) not implemented yet"
end
def template_option(_opt_name, :checkbox, do: _expression) do
"template_option(opt_name, :checkbox) not implemented yet"
end
#
# older insert_object syntax
#
# defmacro insert_object(obj_name, type, opts \\ [])
# defmacro insert_object(obj_name, :text, opts) do
# text_editor(obj_name, opts)
# end
# defmacro insert_object(obj_name, :snippet, opts) do
# snippet(obj_name, opts)
# end
# defmacro insert_object(conn, obj_name, :page_list, opts) do
# page_list(obj_name, opts)
# end
def render(_conn, [partial: _partial_path] = _opts) do
"render(partial: ...) not implemented yet"
end
end