Not so time ago I have spent a lot of time thinking about and prototyping new admin panel for
phoenix. No one loves to write admin panels by himself.
But I have a strong feeling that I need to discuss my ideas with community members before reinventing the wheel.
I am also not quite sure that I can handle a project like that by myself, it requires a lot of skills: choosing good code structure, creating good API design. I will highly appreciate any help with it.
I am also looking for guidance from more experienced
I have tried
ex_admin and found it great. I have even contributed to the project. By there are some issues with it and something does not feel right. I can name several things:
- It uses
dsl, which is pure magic. It is stated to be inspired by ‘ActiveAdmin’ (I have never actually seen Ruby on Rails in my life). But
elixiris not like
ruby. It is hard to reimplement some features.
- It uses it’s own tools for almost anything: generating html, routing, etc. It does not follow the same rules and principles which
- Source code is very hard to read and modify. It almost impossible to find a bug there. That is caused by custom rich
dsland a lot of macro magic.
- Frontend is tightly coupled with the backed, in contrast to phoenix-js which is a separate module
Anyway, I am grateful for the great tool I am using on 2 of my projects today.
My core idea is: new tool should reuse existing
phoenix-way of doing things, but include some magic to get rid of (or reduce) the boilerplate code.
I really like routes from
phoenix, so I would like to reuse them. Here’s a brief example of what seems to me as a reasonable API:
defmodule TestProject.Router do use TestProject.Web, :router use PhoenixAdmin.Router alias TestProject.Accounts.User # Pipelines: pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash end pipeline :require_auth do plug Guardian.Plug.EnsureAuthenticated, handler: TestProject.AuthController end # Scopes: scope "/admin" do pipe_through :browser # or `:api` if you need only `json` pipe_through :require_auth # you can reuse ANY already existing plugs scope "/user", PhoenixAdmin.CRUD(User) do # Registering model for our basic CRUD controller, # note, that we are using the same DSL as Phoenix itself. resource "/users", UserController, only: [:new, :create, :update, :destroy] # Maybe we should specify context and context functions to work with the objects via context? end end end
This seems to be a standard way of doing things in
phoenix. Where’s the magic? Actually, there’s no magic here. Just pass a regular controller module. It might be even a single controller for both admin and application code. But what to do if that functionality differs?
At first, I thought that passing models and auto-generating controllers and forms from them might be a good idea. Right now I am not so sure.
phoenix uses generators to create new controllers. Maybe we should do so as well? It offers some very good points:
- Have all your code in front of you. Need to modify something? No problem
- You don’t have to learn new
- It is easy to have single code base for your application and admin panel
- Reuse everything!
How generations should work? What are the reasonable defaults?
Forms, views and templates
I like how
phoenix renders templates and
json. It uses pretty much the same API.
So, let’s reuse it!
We also need to provide some kind of default template: AdminLTE or similar.
And it feels like providing some helper functions via
View to render styled fields (or other useful parts) is pretty useful.
And also maybe something like “dynamic forms” described here.
It should be possible to include, modify, and extend already existing admin templates and template parts.
Admin panels have a lot of configuration. Like (warning, django terms ahead):
search_fields, and so on.
I see it like this:
defmodule AdminTest.Web.UserController do use AdminTest.Web, :controller defimpl PhoenixAdmin.Config do # Here's a configuration for this specific controller: def list_items(val), do: ... def search_items(val), do: ... end end
That’s about it.
What do you think of it? Are there any other ideas?
Would you use such a thing? Or not? Why?
Here’s a link to the repo: https://github.com/elixir-lang-moscow/phoenix_admin
Here’s a link to the package (there’s currently nothing there): https://hex.pm/packages/phoenix_admin
If you would like to contribute to the development, it is more than welcomed. We can continue a discussion on github.