Skip to content

Commit 75c9409

Browse files
authored
Merge pull request #16 from plotly/configure-circleci
Configure CircleCI for Dash.jl repository
2 parents 44735ee + 33e55ee commit 75c9409

15 files changed

+781
-124
lines changed

.circleci/config.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
version: 2
2+
3+
jobs:
4+
5+
test:
6+
working_directory: /root/project/Dash
7+
8+
docker:
9+
- image: julia:latest
10+
11+
steps:
12+
- checkout
13+
14+
- run:
15+
name: ℹ️ CI Context
16+
command: |
17+
echo "TRIGGERER: ${CIRCLE_USERNAME}"
18+
echo "BUILD_NUMBER: ${CIRCLE_BUILD_NUM}"
19+
echo "BUILD_URL: ${CIRCLE_BUILD_URL}"
20+
echo "BRANCH: ${CIRCLE_BRANCH}"
21+
echo "RUNNING JOB: ${CIRCLE_JOB}"
22+
echo "JOB PARALLELISM: ${CIRCLE_NODE_TOTAL}"
23+
echo "CIRCLE_REPOSITORY_URL: ${CIRCLE_REPOSITORY_URL}"
24+
echo $CIRCLE_JOB > circlejob.txt
25+
26+
- run:
27+
name: 🔎 Unit tests
28+
command: |
29+
julia -e 'using Pkg; Pkg.update(); Pkg.add(PackageSpec(path=pwd())); Pkg.build("Dash"); Pkg.test("Dash", coverage=true);'
30+
31+
workflows:
32+
version: 2
33+
build:
34+
jobs:
35+
- "test"

src/ComponentPackages.jl

+11
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ module ComponentPackages
4343
)
4444
end
4545

46+
function components_js_sources(prefix = ""; debug=false)
47+
type = debug ? :dev : :prod
48+
result = []
49+
50+
for p in values(_components_packages)
51+
for script in p.scripts[type]
52+
push!(result, "$(prefix)_dash-component-suites/$(p.package_name)/$(script)")
53+
end
54+
end
55+
return result
56+
end
4657

4758

4859

src/Dash.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ export dash, Component, Front, @use, <|, @callid_str, CallbackId, callback!,
1515
run_server, PreventUpdate, no_update, @wildprop
1616

1717
ComponentPackages.@reg_components()
18+
include("utils.jl")
19+
include("config.jl")
1820
include("app.jl")
21+
include("index_page.jl")
1922
include("handlers.jl")
20-
include("utils.jl")
2123

2224

2325
@doc """
@@ -91,4 +93,5 @@ function run_server(app::DashApp, host = HTTP.Sockets.localhost, port = 8080; de
9193
HTTP.serve(handler, host, port)
9294
end
9395

96+
9497
end # module

src/app.jl

+215-54
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
const IdProp = Tuple{Symbol, Symbol}
22

3+
const default_index = """<!DOCTYPE html>
4+
<html>
5+
<head>
6+
{%metas%}
7+
<title>{%title%}</title>
8+
{%favicon%}
9+
{%css%}
10+
</head>
11+
<body>
12+
{%app_entry%}
13+
<footer>
14+
{%config%}
15+
{%scripts%}
16+
{%renderer%}
17+
</footer>
18+
</body>
19+
</html>"""
20+
21+
22+
323
struct CallbackId
424
state ::Vector{IdProp}
525
input ::Vector{IdProp}
@@ -34,33 +54,43 @@ mutable struct Layout
3454
component::Union{Nothing, Component}
3555
end
3656

57+
const ExternalSrcType = Union{String, Dict{String, String}}
58+
59+
struct DashConfig
60+
external_stylesheets ::Vector{ExternalSrcType}
61+
external_scripts ::Vector{ExternalSrcType}
62+
url_base_pathname ::Union{String, Nothing} #TODO This looks unused
63+
requests_pathname_prefix ::String
64+
routes_pathname_prefix ::String
65+
assets_folder ::String
66+
assets_url_path ::String
67+
assets_ignore ::String
68+
serve_locally ::Bool
69+
suppress_callback_exceptions ::Bool
70+
eager_loading ::Bool
71+
meta_tags ::Vector{Dict{String, String}}
72+
index_string ::Union{String, Nothing}
73+
assets_external_path ::Union{String, Nothing}
74+
include_assets_files ::Bool
75+
show_undo_redo ::Bool
76+
end
77+
3778
"""
3879
struct DashApp <: Any
3980
40-
Representation of Dash application
81+
Representation of Dash application.
82+
83+
Not meant to be constructed directly, use `dash` function instead.
4184
"""
4285
struct DashApp
4386
name ::String
87+
config ::DashConfig
4488
layout ::Layout
4589
callbacks ::Dict{Symbol, Callback}
46-
external_stylesheets ::Vector{String}
47-
external_scripts ::Vector{String}
48-
url_base_pathname ::String
49-
assets_folder ::String
50-
callable_components ::Dict{Symbol, Component}
51-
function DashApp(name::String;
52-
external_stylesheets ::Vector{String} = Vector{String}(),
53-
external_scripts ::Vector{String} = Vector{String}(),
54-
url_base_pathname="/",
55-
assets_folder::String = "assets")
56-
57-
new(name, Layout(nothing), Dict{Symbol, Callback}(),
58-
external_stylesheets, external_scripts,
59-
url_base_pathname, assets_folder,
60-
Dict{Symbol, Component}()
61-
62-
)
63-
end
90+
callable_components ::Dict{Symbol, Component}
91+
92+
DashApp(name::String, config::DashConfig) = new(name, config, Layout(nothing), Dict{Symbol, Callback}(), Dict{Symbol, Component}())
93+
6494
end
6595

6696
function layout!(app::DashApp, component::Component)
@@ -78,59 +108,190 @@ function Base.getproperty(app::DashApp, name::Symbol)
78108
name == :layout ? getlayout(app) : Base.getfield(app, name)
79109
end
80110

81-
111+
82112

83113

84114

85115
"""
86-
dash(name::String; external_stylesheets ::Vector{String} = Vector{String}(), url_base_pathname::String="/")
87-
dash(layout_maker::Function, name::String; external_stylesheets ::Vector{String} = Vector{String}(), url_base_pathname::String="/")
116+
dash(name::String;
117+
external_stylesheets,
118+
external_scripts,
119+
url_base_pathname,
120+
requests_pathname_prefix,
121+
routes_pathname_prefix,
122+
assets_folder,
123+
assets_url_path,
124+
assets_ignore,
125+
serve_locally,
126+
suppress_callback_exceptions,
127+
eager_loading ,
128+
meta_tags,
129+
index_string,
130+
assets_external_path,
131+
include_assets_files,
132+
show_undo_redo
133+
)
88134
89-
Construct a dash app using callback for layout creation
135+
Construct a dash app
90136
91137
# Arguments
92-
- `layout_maker::Function` - function for layout creation. Must has signature ()::Component
93-
- `name::String` - Dashboard name
94-
- `external_stylesheets::Vector{String} = Vector{String}()` - vector of external css urls
95-
- `external_scripts::Vector{String} = Vector{String}()` - vector of external js scripts urls
96-
- `url_base_pathname::String="/"` - base url path for dashboard, default "/"
138+
- `name::String` - The name of your application
97139
- `assets_folder::String` - a path, relative to the current working directory,
98-
for extra files to be used in the browser. Default `"assets"`
140+
for extra files to be used in the browser. Default ``'assets'``.
99141
100-
# Examples
101-
```jldoctest
102-
julia> app = dash("Test") do
103-
html_div() do
104-
html_h1("Test Dashboard")
105-
end
106-
end
107-
```
108-
"""
142+
- `assets_url_path::String` - The local urls for assets will be:
143+
``requests_pathname_prefix * assets_url_path * "/" * asset_path``
144+
where ``asset_path`` is the path to a file inside ``assets_folder``.
145+
Default ``'assets'`.
146+
147+
148+
- `assets_ignore::String` - [IN DEVELOPMENT] A regex, as a string to pass to ``Regex``, for
149+
assets to omit from immediate loading. Ignored files will still be
150+
served if specifically requested. You cannot use this to prevent access
151+
to sensitive files.
152+
:type assets_ignore: string
153+
154+
- `assets_external_path::String` - [IN DEVELOPMENT] an absolute URL from which to load assets.
155+
Use with ``serve_locally=false``. Dash can still find js and css to
156+
automatically load if you also keep local copies in your assets
157+
folder that Dash can index, but external serving can improve
158+
performance and reduce load on the Dash server.
159+
160+
161+
- `include_assets_files::Bool` - [IN DEVELOPMENT] Default ``true``, set to ``False`` to prevent
162+
immediate loading of any assets. Assets will still be served if
163+
specifically requested. You cannot use this to prevent access
164+
to sensitive files.
165+
166+
167+
- `url_base_pathname::String`: A local URL prefix to use app-wide.
168+
Default ``nothing``. Both `requests_pathname_prefix` and
169+
`routes_pathname_prefix` default to `url_base_pathname`.
170+
171+
172+
- `requests_pathname_prefix::String`: A local URL prefix for file requests.
173+
Defaults to `url_base_pathname`, and must end with
174+
`routes_pathname_prefix`
175+
176+
177+
- `routes_pathname_prefix::String`: A local URL prefix for JSON requests.
178+
Defaults to ``url_base_pathname``, and must start and end
179+
with ``'/'``.
180+
181+
- `serve_locally`: [IN DEVELOPMENT] If ``true`` (default), assets and dependencies
182+
(Dash and Component js and css) will be served from local URLs.
183+
If ``false`` we will use CDN links where available.
184+
185+
- `meta_tags::Vector{Dict{String, String}}`: html <meta> tags to be added to the index page.
186+
Each dict should have the attributes and values for one tag, eg:
187+
``Dict("name"=>"description", "content" => "My App")``
188+
109189
190+
- `index_string::String`: Override the standard Dash index page.
191+
Must contain the correct insertion markers to interpolate various
192+
content into it depending on the app config and components used.
193+
See https://dash.plotly.com/external-resources for details.
194+
195+
196+
- `external_scripts::Vector`: Additional JS files to load with the page.
197+
Each entry can be a String (the URL) or a Dict{String, String} with ``src`` (the URL)
198+
and optionally other ``<script>`` tag attributes such as ``integrity``
199+
and ``crossorigin``.
200+
201+
- `external_stylesheets::Vector`: Additional CSS files to load with the page.
202+
Each entry can be a String (the URL) or a Dict{String, String} with ``href`` (the URL)
203+
and optionally other ``<link>`` tag attributes such as ``rel``,
204+
``integrity`` and ``crossorigin``.
205+
206+
- `suppress_callback_exceptions::Bool`: Default ``false``: check callbacks to
207+
ensure referenced IDs exist and props are valid. Set to ``true``
208+
if your layout is dynamic, to bypass these checks.
209+
210+
- `show_undo_redo::Bool`: Default ``false``, set to ``true`` to enable undo
211+
and redo buttons for stepping through the history of the app state.
212+
213+
"""
110214
function dash(name::String;
111-
external_stylesheets ::Vector{String} = Vector{String}(),
112-
external_scripts ::Vector{String} = Vector{String}(),
113-
url_base_pathname="/",
114-
assets_folder::String = "assets")
115-
result = DashApp(name,
116-
external_stylesheets=external_stylesheets,
117-
external_scripts=external_scripts,
118-
url_base_pathname=url_base_pathname,
119-
assets_folder = assets_folder
120-
)
215+
external_stylesheets = ExternalSrcType[],
216+
external_scripts = ExternalSrcType[],
217+
url_base_pathname = nothing,
218+
requests_pathname_prefix = nothing,
219+
routes_pathname_prefix = nothing,
220+
assets_folder = "assets",
221+
assets_url_path = "assets",
222+
assets_ignore = "",
223+
serve_locally = true,
224+
suppress_callback_exceptions = false,
225+
eager_loading = false,
226+
meta_tags = Dict{Symbol, String}[],
227+
index_string = default_index,
228+
assets_external_path = nothing,
229+
include_assets_files = true,
230+
show_undo_redo = false
231+
232+
)
233+
234+
235+
config = DashConfig(
236+
external_stylesheets,
237+
external_scripts,
238+
pathname_configs(
239+
url_base_pathname,
240+
requests_pathname_prefix,
241+
routes_pathname_prefix
242+
)...,
243+
absolute_assets_path(assets_folder),
244+
lstrip(assets_url_path, '/'),
245+
assets_ignore,
246+
serve_locally,
247+
suppress_callback_exceptions,
248+
eager_loading,
249+
meta_tags,
250+
index_string,
251+
assets_external_path,
252+
include_assets_files,
253+
show_undo_redo
254+
)
255+
256+
result = DashApp(name, config)
121257
return result
122258
end
123259

124-
function dash(layout_maker::Function, name::String;
125-
external_stylesheets ::Vector{String} = Vector{String}(),
126-
external_scripts ::Vector{String} = Vector{String}(),
127-
url_base_pathname="/",
128-
assets_folder::String = "assets")
260+
function dash(layout_maker ::Function, name;
261+
external_stylesheets = ExternalSrcType[],
262+
external_scripts = ExternalSrcType[],
263+
url_base_pathname = nothing,
264+
requests_pathname_prefix = nothing,
265+
routes_pathname_prefix = nothing,
266+
assets_folder = "assets",
267+
assets_url_path = "assets",
268+
assets_ignore = "",
269+
serve_locally = true,
270+
suppress_callback_exceptions = false,
271+
eager_loading = false,
272+
meta_tags = Dict{Symbol, String}[],
273+
index_string = default_index,
274+
assets_external_path = nothing,
275+
include_assets_files = true,
276+
show_undo_redo = false
277+
)
129278
result = dash(name,
130279
external_stylesheets=external_stylesheets,
131280
external_scripts=external_scripts,
132281
url_base_pathname=url_base_pathname,
133-
assets_folder = assets_folder
282+
requests_pathname_prefix = requests_pathname_prefix,
283+
routes_pathname_prefix = routes_pathname_prefix,
284+
assets_folder = assets_folder,
285+
assets_url_path = assets_url_path,
286+
assets_ignore = assets_ignore,
287+
serve_locally = serve_locally,
288+
suppress_callback_exceptions = suppress_callback_exceptions,
289+
eager_loading = eager_loading,
290+
meta_tags = meta_tags,
291+
index_string = index_string,
292+
assets_external_path = assets_external_path,
293+
include_assets_files = include_assets_files,
294+
show_undo_redo = show_undo_redo
134295
)
135296
layout!(result, layout_maker())
136297
return result

0 commit comments

Comments
 (0)