tmbb

tmbb

Mandarin + Forage - An admin tool for phoenix

I’ve been working on two packages (not on hex.pm yet) to build admin interfaces for phoenix apps:

  • bureaucrat - which contains a bunch of generators to create very feature-rich CRUD views for your resources (with filtering, sorting and proper pagination out of the box)

  • forage (the name comes from the rummage package) - which does the bulk of the work by allowing easy creating of dynamic ecto queries based on plug query parameters. It also contains widgets which make it easy to create search filters, pagination widgets, etc. It acts as a bridge between the form in the frontend and the ecto queries in the backend. Unlike rummage, it’s coupled to plug applications, while rummage tries to be frontend-independent. I don’t think that in the current state of the elixir ecosystem decoupling it from plug is worth it.

Documentation is severely lacking, but those who are interested can look at an example project here: GitHub - tmbb/bureaucrat_demo_app: Demo app for Bureaucrat · GitHub

The packages lack a lot of documentation, and I’ll work on that over the next weeks now that I’m happy with the functionality.

Roadmap

I’m planning on doing the following:

  1. Documentation, documentation, documentation…

  2. In particular, documenting forage’s functionality, because it can be useful outside Bureaucrat. I do try very hard to make it work as a black box, that is, as longa s you use the correct widgets in the frontend things should just work, but people who want to extend it need some guidance.

  3. Make Paginator (a library which I use for pagination) support ecto 3.

  4. Improving forage so that it is less dependent on the Repo. Everything should work with “raw” ecto queries independent of the Repo. That will probably require some PRs to the paginator package which I use for pagination.

  5. Make bureaucrat play better with many-to-many relations. That will require working mostly on forage, and only minor changes to Bureaucrat itself

  6. Make bureaucrat independent of JQuery, and find a better way to packaging the necessary Javascript. The current generated templates get all JS and CSS from a CDN and embed some inline Javascript to make the Select2 widgets work.

  7. Write a proper tutorial, based on [this tutorial](Quick Minimal Application — Flask AppBuilder, for the Flask application framework (which is a python project)

Most Liked

tmbb

tmbb

As it turns out, bureaucrat was already of an elixir package on Hex.

I’ve changed the name to mandarin and published it as it is so that no one else takes the name in the mean time (renaming this project again is a chore I’d like to avoid). To publish mandarin, I’ve had to publish forage too. None of the packages are exactly ready for use in production. They have no tests and the documentation is still lacking.

“Mandarin” was the name given to the official of the Chinese empire by Portuguese explorers in the Far East in the 1500s. It is commonly said to come from the Portuguese word “mandar”, which means “to give orders/boss around”, but this etymology turns out to be fake (although it’s much cooler than the real one). Actually it comes from a Malay word for “boss” in use at the time. Basically a Mandarin is a Chinese bureaucrat, so it is a good replacement name.

Could a nice mod please change the title of this thread to “Mandarin + Forage - An admin tool for Phoenix”?

EDIT: Mandarin has the obvious advantage that it is derived from Portuguese (actually from “Old Portuguese”, because nowadays the word is written as “mandarim”), unlike Bureaucrat, which comes from French. As all French words, it’s impossible to write correctly on the first try, which can lead to countless typos in your code, so maybe this change is for the best :smile: C’est la vie… On the other hand, spelling rules in Portuguese are (mostly) consistent and Portuguese words are easy to write. Which only proves the superiority of the Portuguese language over everything else.

The above is obviously a joke

tmbb

tmbb

Now I believe I’m getting really close to 1.0. The main new features (already reflected in the GitHub repo) are the following:

  • Updated the generators in order to be more compatible with what Phoenix 1.6 generates

  • Made sure all tests pass (the generators weren’t buggy themselves, but the tests hadn’t been updated to reflect changes in the generators)

  • Use “vertical feature folders” which keep your controllers, views and templates together in the same directory, which makes it easy to modify related parts of the source code

  • As a consequence of the above, there is now a mix mandarin.uninstall MyContext which completely purges all the context diurectories and files and all references to that context from the router. This is very useful when your database design is still in flux and you might want to tear down the whole mandarin files and build them again

  • There is now a programatic interface to mandarin generators using the Mandarin.Design module, which allows you to generate the interface for a bunch of schemas from the comfort of an Elixir script instead of having to fiddle with the command line. To keep the design close to the normal Phoenix generators, I’m going to keep the command line interface as the main form of interaction with mandarin, but that might change in a putative 2.0 version

  • Mandarin now includes a mandarin.gen.auth AuthContext User users modelled on the phx.gen.auth generator but with support for “vertical feature folders” and support for prettier forms using forage widgets and a boostrap template by default

Things that haven’t changes:

  • Forage is still coupled to bootstrap; that’s pretty much unavoidable for a library of frontend widgets. The widgets must be styled with something, and bootstrap is still one of the easiest frameworks to use and customize, particularly for something like CRUD pages

  • Mandarin still dumps a bunch of files in your application. I’ve decided that mandarin will continue to focus on code generators instead of macros or other use of compile/runtime metaprogramming. No mandarin code runs at runtime.

  • No integration with LiveView. Simple CRUD pages are easy to do with normal controllers + minimal AJAX and more complex CRUD pages are outside of Mandarin’s scope. I’ve had some succes in integrating AlpineJS into mandarin pages (although neither Mandarin nor Forage contain any direct support for it)

The main problems I’ve had in getting to this stage are the fact that Phoenix continues to change the generators (for the better, of course!) on each minor version, and I took som etime to catch up to it. Although my generators are mostly copied from Phoenix, they have some important customizations, so thet job of updating them is not exactly simple. Note that this is not a case of Phoenix changing in backward-incompatible ways; it’s just a case of generators being different.

dimitarvp

dimitarvp

I’d use something like bureacratic or frontdesk.

Well, this is open source. Assuming a car doesn’t kill you on the spot one morning, you can always hand ownership over to somebody else. I see nothing wrong with a bit more official-looking name.

Where Next?

Popular in Announcing Top

tmbb
I’ve published the first version of my Makeup library. It’s a syntax highlighter for Elixir in the spirit of Pygments, Currently it highl...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
mischov
import Meeseeks.CSS html = HTTPoison.get!("https://news.ycombinator.com/").body for story <- Meeseeks.all(html, css("tr.athing")) do...
New
seancribbs
Today I released a new dialyzer Mix task as the dialyzex package! At the time we started writing this task, the existing dialyzer integra...
New
riverrun
I’ve just released version 3 of Comeonin, a password hashing library. The following small changes have been made: changes to the NIF c...
New
Qqwy
Hello everyone, I wrote a small library today called MapDiff. It returns a map listing the (smallest amount of) changes to get from map...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 13736 119
New
achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New
pkrawat1
Hey guyz We at @aviabird are working on a payment library in elixir/phoenix. We are targeting March 2018 to add 56 Gateways to it. Have...
New

Other popular topics Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30877 112
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement