Skip to content

Add a GitHub action to lint the Markdown. #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Lint Markdown

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm install -g [email protected]
- run: markdownlint '**/*.md' --ignore node_modules
14 changes: 14 additions & 0 deletions .markdownlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# MD001 Header levels should only increment by one level at a time
MD001: false

# MD013 Line length
MD013: false

# MD022 Headers should be surrounded by blank lines
MD022: false

# MD026 Trailing punctuation in header
MD026: false

# MD032 Lists should be surrounded by blank lines
MD032: false
4 changes: 1 addition & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Change Log for Dash for Julia
All notable changes to this project will be documented in this file. This project adheres to Semantic Versioning.



### [UNRELEASED]
## [UNRELEASED]
### Added
- Support for client side callbacks [#30](https://github.com/plotly/Dash.jl/pull/30)
- Support for hot reloading on application or asset changes [#25](https://github.com/plotly/Dash.jl/pull/25)
Expand Down
31 changes: 21 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Dash for Julia
# Dash for Julia

#### Create beautiful, analytic applications in Julia.

Expand Down Expand Up @@ -36,7 +36,7 @@ julia> using DashHtmlComponents
julia> using DashCoreComponents

julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> app.layout = html_div() do
html_h1("Hello Dash"),
html_div("Dash.jl: Julia interface for Dash"),
Expand All @@ -56,18 +56,18 @@ julia> run_server(app, "0.0.0.0", 8080)
```

* The `DashApp` struct represents a dashboard application.
* To make `DashApp` struct use `dash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")`` where `layout_maker` is a function with signature ()::Component
* To make `DashApp` struct use `dash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")` where `layout_maker` is a function with signature ()::Component
* Unlike the Python version where each Dash component is represented as a separate class, all components in Dash.jl are represented by struct `Component`.
* You can create `Component` specific for concrete Dash component by the set of functions in the form ``lowercase(<component package>)_lowercase(<component name>)``. For example, in Python html `<div>` element is represented as `HTML.Div` in Dashboards it is created using function `html_div`
* The list of all supported components is available in docstring for Dashboards module.
* All functions for a component creation have the signature `(;kwargs...)::Component`. List of key arguments specific for the concrete component is available in the docstring for each function.
* Functions for creation components which have `children` property have two additional methods ``(children::Any; kwargs...)::Component`` and ``(children_maker::Function; kwargs..)::Component``. `children` must by string or number or single component or collection of components.
* ``make_handler(app::Dash; debug::Bool = false)`` makes a handler function for using in HTTP package.


__Once you have run the code to create the Dashboard, go to `http://127.0.0.1:8080` in your browser to view the Dashboard!__

### Basic Callback

```jldoctest

julia> using Dash
Expand All @@ -78,7 +78,7 @@ julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwg

julia> app.layout = html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div")
html_div(id = "my-div")
end

julia> callback!(app, Output("my-div", "children"), Input("my-id", "value")) do input_value
Expand All @@ -87,22 +87,24 @@ end

julia> run_server(app, "0.0.0.0", 8080)
```

* You can make your dashboard interactive by register callbacks for changes in frontend with function ``callback!(func::Function, app::Dash, output, input, state)``
* Inputs and outputs (and states, see below) of callback can be `Input`, `Output`, `State` objects or vectors of this objects
* Callback function must have the signature(inputs..., states...), and provide a return value comparable (in terms of number of elements) to the outputs being updated.

### States and Multiple Outputs

```jldoctest
julia> using Dash
julia> using DashHtmlComponents
julia> using DashCoreComponents

julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> app.layout = html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div"),
html_div(id = "my-div2")
html_div(id = "my-div2")
end

julia> callback!(app, [Output("my-div"."children"), Output("my-div2"."children")], Input("my-id", "value"), State("my-id", "type")) do input_value, state_value
Expand Down Expand Up @@ -131,25 +133,30 @@ html_div(id="outer-div") do
end
end
```

### application and layout:

* python:

```python
app = dash.Dash("Test", external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[....])
```

* Dash.jl:

```julia
app = dash("Test", external_stylesheets=external_stylesheets)
app = dash("Test", external_stylesheets=external_stylesheets)

app.layout = html_div() do
......
end

```

### callbacks:

* Python:

```python
@app.callback(Output('output', 'children'),
[Input('submit-button', 'n_clicks')],
Expand All @@ -159,7 +166,9 @@ def update_output(n_clicks, state1, state2):
.....

```

* Dash.jl:

```julia
callback!(app, Output("output", "children"),
[Input("submit-button", "n_clicks")],
Expand All @@ -168,9 +177,11 @@ callback!(app, Output("output", "children"),
.....
end
```

Be careful - in Dash.jl states come first in an arguments list.

### JSON:
I use JSON2.jl for JSON serialization/deserialization, so in callbacks all JSON objects are `NamedTuples` rather than dictionaries. Within component properties you can use both `Dict` and `NamedTuple` for JSON objects.

I use JSON2.jl for JSON serialization/deserialization, so in callbacks all JSON objects are `NamedTuples` rather than dictionaries. Within component properties you can use both `Dict` and `NamedTuple` for JSON objects.

Note when declaring elements with a single properly that `layout = (title = "Test graph")` is not interpreted as a `NamedTuple` by Julia - you'll need to add a comma when declaring the layout, e.g. `layout = (title = "Test graph",)`
22 changes: 17 additions & 5 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Julia backend for [Plotly Dash](https://github.com/plotly/dash)
* [dash-bootstrap-components](https://github.com/facultyai/dash-bootstrap-components) added with prefix dbc. Examples of use will be soon
* pass_changed_props argument added to [`callback!`](@ref) function. For details see docs of [`callback!`](@ref)


## Version 0.2.5 released

* Now you can use `PlotlyBase.Plot` to work with the `figure` property of the `dcc_graph` component. Examples are: [Plot usage in layout](https://github.com/waralex/DashboardsExamples/blob/master/dash_tutorial/2_dash_layout_4.jl), [Plot usage in callback](https://github.com/waralex/DashboardsExamples/blob/master/dash_tutorial/3_basic_dash_callbacks_2.jl)
Expand Down Expand Up @@ -52,6 +51,7 @@ end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)
```

* The `Dash` struct represent dashboard application.
* The constructor for `Dash` struct is ``Dash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")`` where `layout_maker` is a function with signature ()::Component
* Unlike the python version where each Dash component is represented as a separate class, all components in Dashboard are represented by struct `Component`.
Expand All @@ -61,17 +61,17 @@ julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)
* Functions for creation components which have `children` property have two additional methods ``(children::Any; kwargs...)::Component`` and ``(children_maker::Function; kwargs..)::Component``. `children` must by string or number or single component or collection of components
* ``make_handler(app::Dash; debug::Bool = false)`` makes handler function for using in HTTP package


__Once you have run the code to create the Dashboard, go to `http://127.0.0.1:8080` in your browser to view the Dashboard!__

### Basic Callback

```jldoctest
julia> import HTTP
julia> using Dashboards
julia> app = Dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div")
html_div(id = "my-div")
end
end
julia> callback!(app, callid"my-id.value => my-div.children") do input_value
Expand All @@ -80,20 +80,22 @@ end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)
```

* You can make your dashboard interactive by register callbacks for changes in frontend with function ``callback!(func::Function, app::Dash, id::CallbackId)``
* Inputs and outputs (and states, see below) of callback are described by struct `CallbackId` which can easily created by string macro `callid""`
* `callid""` parse string in form ``"[{state1 [,...]}] input1[,...] => output1[,...]"`` where all items is ``"<element id>.<property name>"``
* Callback function must have the signature(states..., inputs...) and return data for output

### States and Multiple Outputs

```jldoctest
julia> import HTTP
julia> using Dashboards
julia> app = Dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div"),
html_div(id = "my-div2")
html_div(id = "my-div2")
end
end
julia> callback!(app, callid"{my-id.type} my-id.value => my-div.children, my-div2.children") do state_value, input_value
Expand All @@ -103,6 +105,7 @@ end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)
```

* For multiple output callback must return any collection with element for each output

## Comparision with original python syntax
Expand All @@ -124,42 +127,51 @@ html_div(id="outer-div") do
end
end
```

### application and layout:

* python:

```python
app = dash.Dash("Test", external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[....])
```

* Dashboards:

```julia
app = Dash("Test", external_stylesheets=external_stylesheets) do
html_div() do
......
end
end
```

### callbacks:

* python:

```python
@app.callback(Output('output', 'children'),
[Input('submit-button', 'n_clicks')],
[State('state-1', 'value'),
State('state-2', 'value')])
def update_output(n_clicks, state1, state2):
.....

```

* Dashboards:

```julia
callback!(app, callid"""{state1.value, state2.value}
submit-button.n_clicks
=> output.children""" ) do state1, state2, n_clicks
.....
end
```

Be careful - in Dashboards states came first in arguments list

### json:

I use JSON2 for json serialization/deserialization, so in callbacks all json objects are NamedTuples not Dicts. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: `layout = (title = "Test graph")` is not interpreted as NamedTuple by Julia - you need add comma at the end `layout = (title = "Test graph",)`