LiveAdmin - Phoenix admin UI built on LiveView

Thanks @tfwright and wanted to add a note here that LiveAdmin was the only admin UI that worked out of the box for our multi-app, multi-repo use case. I have documented the use case and approach in case it helps anyone else.

1 Like

I would suggest adding screenshots or an example app to the GH repo for people to play around with and decide if they want to use this.

5 Likes

As I mentioned earlier in the thread, it is dead simple to add live admin to your Phoenix project just to test it out. After adding to deps and installing, just add live_admin "/admin", resources: [MyApp.SomeEctoSchema] and config :live_admin, ecto_repo: MyApp.Repo to your config.

However, if you have Docker setup, I also went ahead and added instructions for running the dev environment to the readme: GitHub - tfwright/live_admin: Low-config Admin UI for Phoenix apps, built on LiveView. The dev app has examples demonstrating more advanced use of configuration, including overrides.

Hi. Hope you’re doing well!

What you get out of the box for 3 lines of code is pretty great. More documentation would be very helpful.

Reading through the example development app, It seemed that render_for_admin, but is there an equivalent for form inputs? I want to change an {:array, :string} field to to pass in a set of options or use a custom searchselect based on tomselect or choice.js instead of checkboxes.

There is not currently a way to override how specific form inputs are rendered. For custom form functionality it is necessary to override the entire form component. I have had requests for more atomic overrides but I am reluctant to go down that path because at a certain point it just makes more sense to use generators. The intended use case for LiveAdmin is a private, internal app with minimal customization required.

However, it is possible to achieve what you want by simply copying the existing form component, customizing only the desired functionality (in your case the array input), and then setting the customized version as an override in the app config: config :live_admin, components: [form: YourApp.CustomFormComponent] (assuming you want all array inputs to work the same way–it is also possible to config the override for specific schemas). That said, for obvious reasons I can’t guarantee an input constructed with a 3rd party lib will work out of the box with LiveAdmin’s changeset handling–it might be necessary to make other customizations–but I wouldn’t expect it would take much since arrays are not a big problem for HTML.

And yes, more documentation would be great. I’ll join the other OS maintainers in saying, PRs welcome! I’ll be a lot more motivated to concentrate on docs myself once I am ready to release 1.0.

2 Likes

New release v0.9.0 :champagne:

API changes

Star attraction is a completely overhauled router config API. This was initially inspired by questions raised in this thread about the proper place for configuration, which lead to my realizing that although it was technically possible to run multiple instances of live_admin in a single app, this was pretty cumbersome (see Allow admin-instance resource config · Issue #34 · tfwright/live_admin · GitHub and support configuring via the router rather than app config by mayel · Pull Request #33 · tfwright/live_admin · GitHub).

The refactor essentially consists of 2 main parts:

  1. The live_admin macro now takes a block, in which you specify each resource route using a new admin_resource macro.
  2. Instead of passing a list of config options directly, you pass a module which uses the LiveAdmin.Resource module, and all “extra” resource configuration is specified there, with the exception of slug_with (“general” configuration will still be passed to live_admin)

So, assuming you had this in 0.8.x:

defmodule MyApp.Router do
  import LiveAdmin.Router

  live_admin "/admin", title: "My Admin UI", resources: [{MyApp.FooSchema, slug_with: "foos", label_with: "Foo"}]
end

You must now do this after updating to 0.9:

defmodule MyApp.FooSchema do
  use LiveAdmin.Resource, label_with: "Foo"
end

defmodule MyApp.Router do
  import LiveAdmin.Router

  live_admin "/admin", title: "My Admin UI" do
    admin_resource "/foos", MyApp.FooSchema
  end
end

Note that the “resource” module can be any module, but if it is not an Ecto schema, then the schema option must be specified. Additionally, it is now possible to specify the ecto_repo option at the live_admin and/or resource level, as was already the case with most other configs. For more information consult the LiveAdmin.Resource and LiveAdmin.Router module docs.

UI changes

Field “type” classes are now on the group rather than the specific input. This should make it slightly easier to target various related elements in the form. This should only affect you if you were overriding any of the .field__foo classes. You will need to update the selectors for any such overrides to be something like .field__foo input, but this will vary from case to case. Apologies to anyone affected since obviously this will be somewhat tedious. I am really hoping to keep FE changes to a minimum going forward, and then frozen for major versions after 1.0.

6 Likes

I really like the changes to the routing API! Feels much more natural and will have better editor support (completion, hover docs) vs. a large config structure.

1 Like

Very glad to hear that. I really resisted going in this direction because of the apparent decrease in flexibility. I even briefly considered adding a good amount of extra code to make a backwards “compatiblish” syntax where the options could be passed in a separate 3rd argument to admin_resource. I guess I would still consider that if people request it, but eventually I ended up admitting that in my own use I was either not passing any options at all, in which the line in the schema seemed fine, or the options came with custom functions that–being admin specific–felt really wrong in the schema and so needed a dedicated module anyway.

1 Like

0.10.0 is a big one :face_exhaling:

Feature highlights:

  • added i18n support - use Gettext to translate LiveAdmin copy for non-English speakers, and/or use your own custom terminology in place of what I’ve chosen
  • added single record view (link added to :hamburger: menu) - no more linking to the edit view!
  • added an on_mount callback option to the admin_resource helper - use this to automatically add metadata to your session, which you can then use in your overrides

API changes:

  • The global prefix_options config has been removed in favor of a prefixes function on your Repo module
  • No really public API, but the route_with_params helper has changed a bit so if you are using it in component overrides you should check out changes: Refactor route helper · tfwright/live_admin@e5de5a8 · GitHub
  • LiveAdmin.render_field/3 has been removed. again, not really public API

…I guess that’s it. Well, it felt like a lot :sweat_smile:

Overall upgrading from 0.9.x should not be a big lift, but as usual let me know if you have trouble, and I will add more details here.

9 Likes

Nice library. Desperately needs more documentation though. Specifically, detailed examples of how to override the various rendering functions would be a huge help. For example, I hooked it up to my User schema, and the users table by default is displaying the password_hash field!

Admittedly not that detailed, but there are docs for configuring a resource. Check out the hidden_fields option.

There’s also an example of it (and most other options) in the dev app. If you have docker installed it’s easy to spin up locally and see it in action.

For your case in particular, are you using the redact option in your schema? Or is there another reason you would not expect that field to appear with the others?

0.11.0 released

  • Plural embed sorting
  • Batch actions (including delete)
  • Require LiveView 0.19.x

Rest of changes are CSS/UX improvements

2 Likes

Is there a way to configure a resource to not use the primary key :id? It looks like it attaches an order by ID on the end of the default list function and passing sort_attr: to the use macro doesn’t seem to solve it :frowning:

Basically I want to override this notification: live_admin/lib/live_admin/resource.ex at c51284282c94edf3965fabd5aa1eed8cf17c16f7 · tfwright/live_admin · GitHub

Unfortunately there’s no way to currently override just the sorting logic, you can however write your own implementation of the list function and configure list_with to use that. The build_list function you link to is the default implementation, so you could copy that and just change the sort line. Just note that the config function takes slightly different args (resource, opts, session) vs (resource, opts, repo). Hope that helps!

Thank you,

I implemented a custom list_with which sidestepped the sort issue but it appears the LiveComponent is using the :id key for a data-attribute which crashes the view :frowning:

Yeah unfortunately it looks like there is an unnecessary assumption about the existence of an id column. If you can open a bug report on the GH repo I will take a closer look.

1 Like

I opened an issue, Support alternate primary keys / remove assumption of `:id` key on struct · Issue #88 · tfwright/live_admin · GitHub I didn’t know how to concisely title it so feel free to change it. Thank you for your quick responses!

1 Like