README.md

# LiveUI

Set of macros for building `Phoenix.LiveView` modules to help manage database records.

This is done by configuring default implementation of `LiveUI` for a given `Ecto.Schema` struct and
initializing basic Index and Show live modules. This will in turn build the infrastructure for displaying
and processing data without need to write boilerplate code associated with `m:Phoenix.LiveView#callbacks` callbacks and HEEX templates.

`LiveUI` has the following features:

* autogenerated views for CRUD operations
* basic protocol implementation with sensible defaults
* sortable tables with pagination
* advanced search form
* format values with css, functions and components
* handles ownership to current user
* handles relations
* handles file uploads
* support to override functions for data processing
* support to override live view callbacks
* custom actions for operations on single and multiple records
* audit with record versioning
* dark and light mode
* debug mode that displays socket assigns

`LiveUI` is possible because of these libraries:

* `Cldr`
* `Ecto`
* `Faker`
* `Flop`
* `LiveInspect`
* `LiveSelect`
* `PaperTrail`
* `PetalComponents`
* `Phoenix`

## Installation

* add entry to `content` list in `assets/tailwind.config.js` - `../lib/live_ui/**/*.*ex`
* add line to `assets/css/app.css` - `@import '../../../live_ui/lib/live_ui/assets/default.css'`
* modify `root.html.heex` template - `<body class="bg-amber-50 dark:bg-gray-900 antialiased">`
* add `js-cookie` to `js/vendor` for theme switcher - <https://github.com/js-cookie/js-cookie>
* add theme switcher hook to `assets/js/app.js`

  ```javascript
  const ColorSchemeHook = {
    deadViewCompatible: true,
    mounted() {
      this.init()
    },
    updated() {
      this.init()
    },
    init() {
      initScheme()
      this.el.addEventListener("click", window.toggleScheme)
    },
  }
  ```

* add switcher code to head in `root.html.heex` - `<LiveUI.Components.Core.color_scheme_switch_js />`
* add switcher icon to body in `root.html.heex` - `<LiveUI.Components.Core.color_scheme_switch />`

### Cldr

Add `Cldr` module:

``` elixir
  defmodule MyApp.Cldr do
    use Cldr,
      default_locale: "en",
      otp_app: :my_app,
      providers: [Cldr.Number, Money, Cldr.Calendar, Cldr.DateTime],
      gettext: MyAppWeb.Gettext
  end
```

### LiveSelect

Add hook to `assets/js/app.js` - <https://hexdocs.pm/live_select/readme.html#javascript-hooks>

### Petal components

Instalation guide - <https://petal.build/components#install_petal_components>

## Configuration

```elixir
# live ui
config :live_ui,
  debug: true,
  repo: MyApp.Repo,
  cldr: MyApp.Cldr,
  ignored_fields: [:token, :hashed_password, :first_version_id, :current_version_id]

# petal components
config :petal_components, :error_translator_function, {MyAppWeb.CoreComponents, :translate_error}

# flop
config :flop, repo: MyApp.Repo, default_limit: 10, max_limit: 100

# cldr
config :ex_cldr, default_backend: LiveUI.Cldr
config :my_app, LiveUI.Cldr, locales: ["en"]

# paper trail (optional)
config :paper_trail,
  repo: MyApp.Repo,
  originator: [name: :user, model: MyApp.User],
  strict_mode: true
```

There is a sample aplication bundled with the project that has all these set up, just run
`mix ecto.setup` to generate some random data and start the server with `iex -S mix phx.server`.
Admin credentials are `admin@example.com/password`.

## Minimal setup

Ecto schema:

```elixir
defmodule MyApp.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :email, :string
    timestamps()
  end
end
```

Router entry:

```elixir
scope "/", MyAppWeb do
  live_ui("/users", UserLive, MyApp.User)
end
```

Protocol file:

```elixir
defimpl LiveUI, for: MyApp.User do
  use LiveUI.Protocol
end
```

Live modules:

```elixir
defmodule MyAppWeb.UserLive.Index do
  use LiveUI.Views.Index, for: MyApp.User
end

defmodule MyAppWeb.UserLive.Show do
  use LiveUI.Views.Show, for: MyApp.User
end
```

## Is it any good?

[Yes](https://news.ycombinator.com/item?id=3067434)