https://github.com/jamesgary/elm-config-ui
Config editor for elm
https://github.com/jamesgary/elm-config-ui
Last synced: 3 months ago
JSON representation
Config editor for elm
- Host: GitHub
- URL: https://github.com/jamesgary/elm-config-ui
- Owner: jamesgary
- License: mit
- Created: 2019-05-17T10:25:56.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2021-04-20T20:18:02.000Z (over 4 years ago)
- Last Synced: 2023-08-08T20:39:25.921Z (over 2 years ago)
- Language: Elm
- Homepage:
- Size: 510 KB
- Stars: 27
- Watchers: 4
- Forks: 4
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-ccamel - jamesgary/elm-config-ui - Config editor for elm (Elm)
README
# elm-config-gui
## ⚠️ Note: Experimental, and likely to change! ⚠️
Have a bunch of magic numbers you want to tweak in the browser? Tired of making a `Msg` for every single field? Try `elm-config-gui`!
`elm-config-gui` adds a mini-editor into the browser to let you update values (`Int`, `Float`, `String`, and `Color`) on the fly without refreshing. Check out a live example [here](https://elm-boids-demo.s3-us-west-1.amazonaws.com/index.html)!

This package has the following features:
- Mini-editor in the browser to let you update config values on the fly without refreshing
- Automatically save changes to localStorage
- Encodes config data to JSON so you can save in a more persistent `.json` file
This module has a **javascript dependency** that sets up webcomponents for saving to localstorage and handling pointerlock for infinite dragging. It also uses a **CLI tool** for generating your `Config.elm` file. Check out the examples directory to see how it all works!
This is meant to be used a dev-facing tool. Hence, there's limited customizability for things like the view. For a fully customizable editor with things like advanced validation and types, feel free to fork and modify!
# Install
Let's say you want a config record that looks like this:
```elm
type alias Config =
{ headerFontSize : Int
, bodyFontSize : Int
, backgroundColor : Color
}
```
Here are the steps to wire everything up:
## Step 1: Generate your `Config.elm`
When adding a new field, such as `headerFontColor`, you'd normally have to update the `type alias Config`, add it to the form in the view, add a `Msg`, encoder, decoder, etc. Turns out there's a lot to do, which can slow down development! If you want all this generated for you, you can instead write a schema file:
```elm
module ConfigSchema exposing (main)
import ConfigFormGenerator exposing (Kind(..))
import Html exposing (Html)
myConfigFields : List ( String, Kind )
myConfigFields =
[ ( "Header Font Size", IntKind "headerFontSize" )
, ( "Body Font Size", IntKind "bodyFontSize" )
, ( "Background Color", ColorKind "backgroundColor" )
-- add more fields here
]
main : Html msg
main =
let
generatedElmCode =
ConfigFormGenerator.toFile myConfigFields
_ =
Debug.log generatedElmCode ""
in
Html.text ""
```
Copy this and save it as `ConfigSchema.elm`. You can now run the following to generate a `Config.elm` file:
```sh
# Compile schema file to tmp js
elm make ConfigSchema.elm --output=~tmp/tmp.js > /dev/null
# Run compiled js with node, which logs out generated elm code, and save to Config.elm:
node ~tmp/tmp.js > Config.elm 2>/dev/null
# You now have a Config.elm file!
```
This will watch for changes to `ConfigSchema.elm` and generate a `Config.elm` file with all the expanded `Config`, `empty`, and `logics` code.
Check out the `run.sh` scripts in the examples to see how to set up a watcher to do this for you automatically!
## Step 2: App initialization
Initialize your elm app using the `elm-config-ui-helper.js` script:
```html
ElmConfigUi.init({
// This is where you'll persist your config data for other users.
// It's fine if this file has just an empty object for now, like "{}".
filepath: "./config.json",
localStorageKey: "my_app",
callback: function(elmConfigUiData) {
// start main Elm app
let app = Elm.Main.init({
node: document.getElementById("elm"),
flags: elmConfigUiData,
});
}
});
```
`elmConfigUiData` will contain json from your file and your localstorage.
## Step 3: Elm app integration
```elm
-- import your generated Config file and the ConfigForm package
import Config exposing (Config)
import ConfigForm exposing (ConfigForm)
-- add config and configForm to your model
type alias Model =
{ ...
-- config is your generated config record,
-- which can be called like model.config.headerFontSize
, config : Config
-- configForm is an opaque type that is managed by ConfigForm
, configForm : ConfigForm
}
init : Json.Encode.Value -> ( Model, Cmd Msg )
init elmConfigUiFlags =
let
-- Initialize your config and configForm,
-- passing in defaults for any empty config fields
( config, configForm ) =
ConfigForm.init
{ flags = elmConfigUiFlags
, logics = Config.logics
, emptyConfig =
Config.empty
{ int = 1
, float = 1
, string = "SORRY IM NEW HERE"
, bool = True
, color = Color.rgba 1 0 1 1 -- hot pink!
}
}
in
( { config = config
, configForm = configForm
}
, Cmd.none
)
type Msg
= ConfigFormMsg (ConfigForm.Msg Config)
| ...
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ConfigFormMsg configFormMsg ->
let
( newConfig, newConfigForm ) =
ConfigForm.update
Config.logics
model.config
model.configForm
configFormMsg
in
( { model
| config = newConfig
, configForm = newConfigForm
}
, Cmd.none
)
-- Lastly, lets add the form to the view!
view : Model -> Html Msg
view model =
Html.div
-- some nice styles to render it on the right side of the viewport
[ style "padding" "12px"
, style "background" "#eec"
, style "border" "1px solid #444"
, style "position" "absolute"
, style "height" "calc(100% - 80px)"
, style "right" "20px"
, style "top" "20px"
]
[ ConfigForm.view
ConfigForm.viewOptions
Config.logics
model.configForm
|> Html.map ConfigFormMsg
-- As a developer, you'll want to save your tweaks to your config.json.
-- You can copy/paste the content from this textarea to your config.json.
-- Then the next time a new user loads your app, they'll see your updated config.
, Html.textarea []
[ ConfigForm.encode model.configForm
|> Json.Encode.encode 2
|> Html.text
]
]
```
# Todo
New features
- Undo/redo
- Reset to default
- Indicator for vals that differ from file (or that are entirely new)
- Save scrolltop
- Fancy (or custom) kinds, like css or elm-ui attributes?
Optimizations
- Cleaner run script (remove duplication and tmp file?)
Tests!