1
0
Fork 0
arcology-elixir/page_controller.org

4.0 KiB

Arcology Page Controller

The Arcology is a Phoenix Elixir application, this page presents a Phoenix controller ArcologyWeb.PageController responsible for loading Arcology.Page structures and presenting the compiled HTML to the page via ArcologyWeb.PageView. The first implementation of this became a mess of mixed concerns, and I'm hoping I can do a bit better this time around.

Page routing in Arcology is based around keywords in the org-mode documents formatted as #+ARCOLOGY_KEY: site/slug, where slug can contain anything which is URL safe, and site is a mnemonic system based on domain to site mapping in the ArcologyWeb.Router1.

ArcologyWeb.PageController's :local action

require Logger

def local(conn, %{"site" => site, "slug" => slug}) do
  string_slug =
    slug
    |> Enum.join("/")
    |> String.replace(~r/.html$/, "")
    |> URI.decode()

  stringword = "#{site}/#{string_slug}"
  keywords = Arcology.Roam.Keyword.get("ARCOLOGY_KEY", stringword)
  if(Enum.count(keywords) > 0, do: Logger.warn("Multiple files for ARCOLOGY_KEY " <> stringword))

  if Enum.count(keywords) == 0 do
    Logger.warn("No file for ARCOLOGY_KEY " <> stringword)

    conn
    |> put_status(:not_found)
    |> put_view(ArcologyWeb.ErrorView)
    |> render("404.html")
  else
    page =
      keywords
      |> Enum.at(0)
      |> Map.get(:f)
      |> Arcology.Roam.File.preloads()
      |> Arcology.Page.from_file()
      |> Arcology.Page.with_localized_html()

    conn
    |> render(:page, %{
      page: page,
      site_title: "Arcology Garden",
      page_title: Enum.at(page.titles, 0)
    })
  end
end

Org Page Template

This template using the Foundation HTML framework for its semantic markup. It expects an Arcology.Page with html_status: :localized assigned to @page, a string assigned to @page_title and the app.html.eex template needs a string assigned to @site_title.

<div class="grid-container">
  <div class="grid-x">
    <div class="12-small cell">
      <h1><%= @page_title %>
        <%= if @page.reference do %>
          <small>[<%= link "ref", to: @page.reference.ref %>]</small>
        <% end %>
      </h1>
    </div>
    <div class="tags">
      Tags:&nbsp;
      <%= if(@page.tags) do %>
        <%= for tag <- @page.tags do %>
          <span class="tag">
            <%= raw(tag) %>
          </span>
        <% end %>
      <% end %>
    </div>
    <div class="12-small cell">
      <%= raw(@page.html) %>
    </div>
  </div>
  
  <%= if length(@page.backlinks) > 0 do %>
    <hr/>
    <div class="grid-x">
      <div class="12-small cell" style="max-height: 40em; overflow: scroll;">
        <h2>This is Referenced</h2>
        <%= raw(@page.backlinks_html) %>
      </div>
    </div>
  <% end %>

  <%= if @page.reference do %>
    <hr/>
    <div class="grid-x">
      <div class="12-small cell">
        Reference: 
        <%=  link @page.reference.ref, to: @page.reference.ref %>
      </div>
    </div>
  <% end %>
</div>

ArcologyWeb.PageController Put Together

defmodule ArcologyWeb.PageController do
  use ArcologyWeb, :controller

  <<arcologyweb_local>>

  def index(conn, _params) do
    render(conn, "index.html", %{
      site_title: "Arcology Garden"
    })
  end
end

ArcologyWeb.PageView

defmodule ArcologyWeb.PageView do
  use ArcologyWeb, :view
end

Footnotes

NEXT I would love to find a better place Arcology routing functionality


1