LiveAdmin - Phoenix admin UI built on LiveView

After working on it for a couple of months and using it in production for most of that time, today I’ve released LiveAdmin, a LiveView based Admin UI for Phoenix apps.

Not much to say about it, it follows in the footsteps of Kaffy and ExAdmin before it to provide a pre-rolled “administrator” UI for Ecto/Phoenix apps.

The main thing that sets it apart, aside from using LiveView, is that it has native support for multi tenant applications. I built it primarily to solve my own use case and for the sake of my own curiosity and learning, but its design is also strongly informed by the intention to remain as lean and simple to configure as possible, while providing powerful escape hatches in the form of full view overrides.

Although it is solidly usable now, it is still essentially in the prototype stage, so I would advise trying it out mainly if you have time/energy for a bit of experimentation. That said, I’d really appreciate any testing/feedback and opinions about how to do things differently.

What it has now:

  • Basic CRUD
  • Schema fields autodiscovery
  • Search
  • Editable embeds
  • Editable belongs_to associations via search
  • Resource and record level operations
  • View overrides

Planned:

  • File uploads
  • Dedicated show view
  • Easy CSS overrides
  • Better default CSS
  • Form input overrides

Cheers, and thanks in advance for your thoughts and suggestions.

25 Likes

is there an example repo showing it’s abilities?

At the bottom of the project readme, there is a link to a demo phoenix app with example configuration. You can also run that app locally, but I still need to document the steps for that. For now the easiest way to test it out if you already have a phoenix app set up to use live view is to just add it there, since it is only a few extra lines of config.

2 Likes

Just released 0.2.

Mainly consists of various minor improvements and bugfixes, but it does contain a fix for a somewhat nasty issue that can cause form views to hang, so I would recommend updating.

7 Likes

Hi @tfwright,
Thanks for this super handy library, the setup was a breeze! And the ability to traverse/update belongs_to associations is awesome.

Looking forward to your planned features, in particular - css overrides. (I have already been asked about a ‘dark mode’ :P)

A way to customize the display of particular fields/ecto types would be nice, maybe I missed it in the docs…

I have a bit of UI/display issue with UUID fields out of the box -
image

I dont really care to see the value - but a way to copy it to clipboard would be slick, and maybe just an icon with a title attribute to show the value on hover would be a better way to squeeze it in the cell. A simpler approach might just be truncating via css Text Overflow - Tailwind CSS

Might make a PR if I can figure out a way to pull it off…

Thanks again for your great contribution to the community!

2 Likes

Hi @harmon25, thanks for the kind words and feedback, it’s great to hear someone else is finding the lib useful.

CSS overrides should not be far off at all. Right now CSS is read from a file that is compiled and stored in the package. I think it would be fairly easy to support an option taking a path to any other file to read instead. I can certainly make that a priority in terms of the roadmap. And a little further off, configurable through the UI itself so people don’t have to fight about light vs dark mode :slight_smile:

And agreed that the current UI is not optimal for binary ids. I like the idea of a copy button but I’m wary of cluttering up the table UI too much. I was thinking of adding a modal “show” view though where copy buttons would find a good home.

Let me know what you think, and of course, PRs always welcome.

1 Like

Thanks for this library @tfwright – I agree, things were really easy for me to set up!

The only snag I ran into was in dev while also running the phoenix_profiler, but disabling it resolved everything. I can file an issue with the stacktrace I saw if that’s helpful!

It seems like the best way to display the list view for a resource with longer text fields is to create a custom component for those views, is that correct?

How would I go about adding parameters like slugs to the live_admin route? If the route for my resource is /resource/:slug, I would love to tell our users to “just put /admin at the beginning of a resource you want to modify”, so that the resulting admin view is /admin/resource/:slug.

Thanks for your work so far! I see this being really helpful for our team.

1 Like

Hi @jondelmil thanks for trying LiveAdmin out and glad to hear it’s working well for you so far.

Please do open an issue. Of course I’d like to maintain as much compatibility as possible with other libraries, or at least be able to add advice to the README.

It depends on exactly what your need is, but yes, generally the default list view does not make it easy to display the full contents of larger fields. Right now the index is not actually overridable yet so I will add that to my short term todo list as well. Although I’d like to improve the CSS to alleviate the issue short of overrides, which I’d like to be a last resort for real corner cases, and this sounds like a common problem people are facing.

I can’t think of a simple way to handle fully customizable urls right now, although for slugs specifically I think it would be feasible to add an option to customize the id field. I’ll add that to my list as well.

1 Like

Released v0.3.

Notable changes:

  • Fixes enum fields with custom mappings
  • Restructures CSS and exposes override config
  • Adds copy functionality to index
  • Adds override support for index component

As part of the CSS restructuring, color-related CSS declarations were moved to a separate file, which can serve as an example for changing the “theme.” @harmon25 hopefully that facilitates the addition of a dark mode. If you have success with that customization feel free to share it here!–and/or let me know where it could be improved.

After experimenting with a modal “field inspector”, I ended up just adding a copy button. I am still weighing adding a show view, but implementing a modal accessed from the index view introduced too many UX snags so this seemed like the least intrusive way to solve that use case.

Overall I feel like I am really at my limit UI-wise so if anyone has strong opinions about how to improve things I am all ears…I think I spent as much time on the CSS/JS underlying these features as I did on the whole initial prototype :sweat_smile:

2 Likes

Nice release!
The copy feature is super handy!

I just finished with some css tweaks that were pretty easy, here is an example for other folks.

admin_css = """
body {
  /* dark body, with white text */
  background-color: #18181b;
  color: white;
}

.nav {
  /* think a fixed width is better on the nav, was taking up too much valuable space otherwise */
  width: 250px;
  /* slightly lighter colour for the nav */
  background-color: #27272a;
}

/* since the nav is now a fixed width - the content should `flex-grow` to fit remaining width*/
.content {
  flex: 1;
}

/* this is the same as the nav colour*/
.resource__header {
  background-color: #27272a;
}

/* this is all still default, but could be tweaked further */
.resource__action--btn {
  background-color: rgb(67, 56, 202);
  border-color: rgb(67, 56, 202);
  color: rgb(243 244 246);
}

.resource__action--btn:hover {
  background-color: rgb(55 48 163);
  border-color: rgb(67, 56, 202);
}

.nav a:hover {
  background-color: rgb(165 180 252);
}

.toast__container--error {
  border-color: rgb(239, 68, 68);
  color: rgb(239, 68, 68);
}

.toast__container--success {
  border-color: rgb(102, 153, 0);
  color: rgb(102, 153, 0);
}
"""
# pass the override to live_admin app config
config :live_admin,
  ecto_repo: App.Repo,
  css_overrides: admin_css

I think it would be helpful to supply a field_name → class map - for supplying custom classes for each td on a resource row.

Would resolve field → class here - live_admin/index.ex at main · tfwright/live_admin (github.com)

This would allow truncating specific fields like Id's to keep them from wrapping on multiple lines.

Let me know what you think, I might be able to hack together a POC if you like the idea…

1 Like

I think it would be helpful to supply a field_name → class map - for supplying custom classes for each td on a resource row.

This sounds like a great idea!

Generally speaking I think adding classes to any/all elements that wrap what can be considered a UI “unit” (admittedly not a super well-defined category) makes sense to maximize what can be achieved through CSS overrides.

1 Like

I created a fork - and sent a PR that fixes something I noticed in with the custom css applied.

I’ll take a look at adding more custom class stuff in future PRs!

1 Like

v0.4

Very small release with a couple of improvements:

1 Like