Subscribe to access all episodes. View plans →

#124: Admin Pages with Torch

Published October 21, 2020

Elixir 1.10

Torch 3.5


Here we have a new Phoenix application and on it we want to list a of few of the best albums, but as you can see - we don’t have anything displayed yet.

Normally to do that we would use the standard Phoenix generators to create our schemas, controllers, and html templates. Instead in this episode, let’s use Torch.

Torch is an admin generator for Phoenix and Elixir applications. It will give us a really nice UI to add and edit our albums, as well as a filter feature we can use to find different albums. Let’s get started by adding torch to our list of dependencies:

mix.exs

...
defp deps do
  [
    ...
    {:torch, "~> 3.5"}
    ...
  ]
end
...

The we’ll go to command line and get our new dependency.

$ mix deps.get
...
New:
  combine 0.10.0
  filtrex 0.4.3
  timex 3.6.2
  torch 3.5.0
  tzdata 1.0.4

With torch downloaded, let’s configure our app to use it. We’ll open our endpoint.ex module and we’ll add a Plug.Static plug to serve our torch admin pages pasting in the config options specified by Torch.

lib/teacher_web/endpoint.ex

...

plug Plug.Static,
  at: "/torch",
  from: {:torch, "priv/static"},
  gzip: true,
  cache_control_for_etags: "public, max-age=86400",
  headers: [{"access-control-allow-origin", "*"}]

...

Then let’s open our config.exs and configure torch specifying our otp_app and the format of our templates, eex for this applications. Torch also supports slime templates.

config/config.exs

...

config :torch,
  otp_app: :teacher,
  template_format: "eex"

...

With that we can go back to the command line and run mix torch.install.

$ mix torch.install
...
==> teacher
* creating lib/teacher_web/templates/layout/torch.html.eex

This creates a torch.html.eex layout that’s used for our admin templates - let’s open it. We can see that the layout uses a torch theme stylesheet and gives us a section for our authentication links and some other defaults. Since torch creates this inside our application it’s easy to customize it to fit our needs.

Now we’re ready to create our admin pages. Torch uses generators to create admin pages. And because the Torch generators use Phoenix generators under the hood the torch.gen.html task takes all the same arguments as the familiar phx.gen.html task. We’ll create a context module named Recordings a schema module named Album, the table name will be albums, and let’s put this in a web namespace named Admin. This will put our controller and view in “admin” namespace to help keep it separate from the rest of our application.

For our album fields we’ll want an artist, summary, title, and the year it was released. It creates some templates for us as well as a controller, schema, migration, and some tests. Torch then prints out some instructions to get our new admin pages working. We’ve already added Plug.Static to our endpoint.ex so let’s copy the provided resource.

$ mix torch.gen.html Recordings Album albums --web Admin artist:string summary:string title:string year:integer
...
Add the resource to your browser scope in lib/teacher_web/router.ex:

    scope "/admin", TeacherWeb.Admin, as: :admin do
      pipe_through :browser
      ...
      resources "/albums", AlbumController
    end

Remember to update your repository by running migrations:

    $ mix ecto.migrate

Ensure the following is added to your endpoint.ex:

    plug(
      Plug.Static,
      at: "/torch",
      from: {:torch, "priv/static"},
      gzip: true,
      cache_control_for_etags: "public, max-age=86400",
      headers: [{"access-control-allow-origin", "*"}]
    )

Also don't forget to add a link to layouts/torch.html.

    <nav class="torch-nav">
      <!-- nav links here -->
    </nav>

Let’s open our router and then add our albums resource.

lib/teacher_web/router.ex

...

scope "/admin", TeacherWeb.Admin, as: :admin do
  pipe_through :browser

  resources "/albums", AlbumController

end

...

Before we start our application let’s add some album data to it. We’ll open our seeds.exs file and I’ll paste in some album data. With that we can go to the command line and run our database migration.

$ mix ecto.migrate
...

And then seed our database.

$ mix run priv/repo/seeds.exs
...

Then if we clear the screen and start our server.

$ mix phx.server
...

We should be able to open our browser and if we go to the “/admin/albums” route we see our Torch admin is working and displaying our albums.

From our UI we see there is a link to add an album, edit an album, there’s also a section that makes it easy to search for albums. But if we go to our app’s homepage our albums aren’t being displayed. Let’s update our application so that when we add or edit albums via our Torch admin, they’re displayed.

We’ll go to our page_controller.ex and we’ll alias our Recordings module. Then we’ll call Recordings.list_albums to get all our albums and include them in our assigns.

lib/teacher_web/controllers/page_controller.ex

defmodule TeacherWeb.PageController do
  use TeacherWeb, :controller

  alias Teacher.Recordings

  def index(conn, _params) do
    albums = Recordings.list_albums()
    render(conn, "index.html", albums: albums)
  end
end

The let’s open our page index.html.eex template.

Template path: lib/teacher_web/templates/page/index.html.eex

<h1>The best albums</h1>
<table>
  <thead>
    <tr>
      <th>Artist</th>
      <th>Summary</th>
      <th>Title</th>
      <th>Year</th>
    </tr>
  </thead>
  <tbody>
    <%= for album <- @albums do %>
      <tr>
        <td><%= album.artist %></td>
        <td><%= album.summary %></td>
        <td><%= album.title %></td>
        <td><%= album.year %></td>
      </tr>
    <% end %>
  </tbody>
</table>

Now if we go back to the browser. We see our albums are displayed and we’re still able to edit them from our Torch admin. One of the great things about Torch is that because it generates admin files inside our application, it’s incredibly easy to update and customize to fit the needs of your application.

© 2020 HEXMONSTER LLC