solara-ui 1.39.0__py2.py3-none-any.whl → 1.41.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- solara/__init__.py +1 -1
- solara/__main__.py +23 -10
- solara/components/__init__.py +1 -0
- solara/components/component_vue.py +3 -2
- solara/components/input_text_area.py +86 -0
- solara/components/markdown.py +1 -1
- solara/hooks/use_thread.py +4 -4
- solara/lab/components/chat.py +8 -2
- solara/server/assets/style.css +4 -1
- solara/server/flask.py +1 -1
- solara/server/jupyter/server_extension.py +11 -1
- solara/server/jupyter/solara.py +91 -0
- solara/server/patch.py +1 -0
- solara/server/pyinstaller/__init__.py +9 -0
- solara/server/pyinstaller/hook-ipyreact.py +5 -0
- solara/server/pyinstaller/hook-ipyvuetify.py +5 -0
- solara/server/pyinstaller/hook-solara.py +9 -0
- solara/server/qt.py +113 -0
- solara/server/server.py +6 -1
- solara/server/settings.py +1 -0
- solara/server/starlette.py +18 -6
- solara/server/static/highlight-dark.css +1 -1
- solara/server/static/main-vuetify.js +11 -1
- solara/server/static/solara_bootstrap.py +1 -1
- solara/server/templates/loader-solara.html +1 -1
- solara/server/templates/solara.html.j2 +36 -7
- solara/website/assets/custom.css +20 -57
- solara/website/components/__init__.py +2 -2
- solara/website/components/algolia_api.vue +23 -6
- solara/website/components/breadcrumbs.py +28 -0
- solara/website/components/contact.py +144 -0
- solara/website/components/docs.py +11 -9
- solara/website/components/header.py +31 -20
- solara/website/components/markdown.py +12 -1
- solara/website/components/markdown_nav.vue +34 -0
- solara/website/components/sidebar.py +9 -1
- solara/website/pages/__init__.py +93 -254
- solara/website/pages/about/__init__.py +9 -0
- solara/website/pages/about/about.md +3 -0
- solara/website/pages/careers/__init__.py +27 -0
- solara/website/pages/changelog/__init__.py +2 -2
- solara/website/pages/changelog/changelog.md +12 -0
- solara/website/pages/contact/__init__.py +30 -6
- solara/website/pages/documentation/__init__.py +25 -33
- solara/website/pages/documentation/advanced/content/10-howto/40-embed.md +2 -1
- solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +1 -1
- solara/website/pages/documentation/advanced/content/20-understanding/40-routing.md +17 -1
- solara/website/pages/documentation/advanced/content/20-understanding/50-solara-server.md +2 -1
- solara/website/pages/documentation/advanced/content/30-enterprise/00-overview.md +1 -1
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +5 -2
- solara/website/pages/documentation/api/hooks/use_thread.md +6 -0
- solara/website/pages/documentation/components/data/pivot_table.py +2 -2
- solara/website/pages/documentation/components/input/input.py +2 -0
- solara/website/pages/documentation/components/output/sql_code.py +3 -3
- solara/website/pages/documentation/examples/__init__.py +14 -22
- solara/website/pages/documentation/examples/ai/chatbot.py +1 -1
- solara/website/pages/documentation/examples/general/vue_component.py +1 -1
- solara/website/pages/documentation/examples/libraries/altair.py +1 -0
- solara/website/pages/documentation/examples/libraries/bqplot.py +1 -1
- solara/website/pages/documentation/examples/libraries/ipyleaflet.py +1 -1
- solara/website/pages/documentation/examples/libraries/ipyleaflet_advanced.py +1 -1
- solara/website/pages/documentation/examples/utilities/countdown_timer.py +18 -20
- solara/website/pages/documentation/examples/visualization/annotator.py +1 -3
- solara/website/pages/documentation/examples/visualization/linked_views.py +4 -4
- solara/website/pages/documentation/getting_started/content/00-quickstart.md +18 -0
- solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb +2 -2
- solara/website/pages/documentation/getting_started/content/05-fundamentals/10-components.md +19 -14
- solara/website/pages/documentation/getting_started/content/05-fundamentals/50-state-management.md +205 -15
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +3 -1
- solara/website/pages/home.vue +1199 -0
- solara/website/pages/our_team/__init__.py +83 -0
- solara/website/pages/pricing/__init__.py +31 -0
- solara/website/pages/roadmap/__init__.py +11 -0
- solara/website/pages/roadmap/roadmap.md +41 -0
- solara/website/pages/scale_ipywidgets.py +45 -0
- solara/widgets/vue/navigator.vue +46 -16
- solara/widgets/vue/vegalite.vue +18 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/METADATA +2 -2
- {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/RECORD +83 -66
- solara/website/components/hero.py +0 -15
- solara/website/pages/contact/contact.md +0 -17
- {solara_ui-1.39.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.39.0.data → solara_ui-1.41.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.39.0.dist-info → solara_ui-1.41.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Solara Changelog
|
|
2
2
|
|
|
3
|
+
## Version 1.40.0
|
|
4
|
+
* Feature: In Jupyter Notebook and Lab, Solara (server) now renders the [ipypopout](https://github.com/widgetti/ipypopout) window instead of Voila [#805](render ipypopout content in jupyter notebook and lab)
|
|
5
|
+
* Feature: Support styling input field of [ChatInput component](https://solara.dev/documentation/components/lab/chat). [#800](https://github.com/widgetti/solara/pull/800).
|
|
6
|
+
* Feature: [InputTextArea component](https://solara.dev/documentation/components/input/input) for multi line text input. [#801](https://github.com/widgetti/solara/pull/801). Contributed by [Alonso Silva](https://github.com/alonsosilvaallende)
|
|
7
|
+
* Bug Fix: Markdown links triggered a JavaScript error. [#765](https://github.com/widgetti/solara/pull/765)
|
|
8
|
+
|
|
9
|
+
## Version 1.39.0
|
|
10
|
+
|
|
11
|
+
* Feature: Add option to start Solara server on a random unused port (using `--port=0`). [#762](https://github.com/widgetti/solara/pull/762)
|
|
12
|
+
* Bug Fix: Extension checking for e.g. ipyleaflet now work correctly on Amazon SageMaker Studio Lab. [#757](https://github.com/widgetti/solara/pull/757)
|
|
13
|
+
* Bug Fix: Various solara components should now work correctly in notebooks viewed on vscode, colab and voila. [#763](https://github.com/widgetti/solara/pull/763)
|
|
14
|
+
|
|
3
15
|
## Version 1.38.0
|
|
4
16
|
|
|
5
17
|
* Feature: We detect and warn when there are possible reverse proxy or uvicorn misconfigurations. [#745](https://github.com/widgetti/solara/pull/745)
|
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
1
|
import solara
|
|
4
2
|
from solara.website.components.sidebar import Sidebar
|
|
3
|
+
from solara.website.components.contact import Contact
|
|
5
4
|
|
|
6
|
-
title = "Contact"
|
|
7
|
-
HERE = Path(__file__)
|
|
8
|
-
|
|
9
|
-
Page = solara.Markdown(Path(HERE.parent / "contact.md").read_text())
|
|
10
5
|
Sidebar = Sidebar
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@solara.component
|
|
9
|
+
def Page():
|
|
10
|
+
solara.Markdown("""
|
|
11
|
+
# Contact
|
|
12
|
+
|
|
13
|
+
## Business
|
|
14
|
+
|
|
15
|
+
Solara is developed mostly by Maarten Breddels and Mario Buikhuizen, Founders
|
|
16
|
+
of [Widgetti](https://widgetti.io/).
|
|
17
|
+
|
|
18
|
+
For business inquiries, please reach out using the form below, or send an email to [contact@solara.dev](mailto:contact@solara.dev) regarding Solara, or [info@widgetti.io](mailto:info@widgetti.io) regarding more general Jupyter related matters.
|
|
19
|
+
""")
|
|
20
|
+
Contact(
|
|
21
|
+
title="Contact Us", subtitle="Please fill out the form below and we will get back to you as soon as possible.", email_subject="Contact Form Submission"
|
|
22
|
+
)
|
|
23
|
+
solara.Markdown(
|
|
24
|
+
"""
|
|
25
|
+
## Community
|
|
26
|
+
|
|
27
|
+
If you want to share your thoughts, share your experiences, or just want to talk
|
|
28
|
+
to other people using and developing on Solara, consider using [GitHub discussions](https://github.com/widgetti/solara/discussions) for asynchronous discussions
|
|
29
|
+
or consider joining discord for more synchronous discussions.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
[](https://discord.gg/dm4GKNDjXN)
|
|
33
|
+
"""
|
|
34
|
+
)
|
|
@@ -17,34 +17,28 @@ def Algolia():
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
@solara.component
|
|
20
|
-
def Page(
|
|
20
|
+
def Page():
|
|
21
21
|
# show a gallery of all the api pages
|
|
22
22
|
router = solara.use_router()
|
|
23
23
|
route_current = router.path_routes[-2]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
},
|
|
41
|
-
):
|
|
42
|
-
with solara.Column(style={"height": "100%", "flex-grow": "1", "background-color": "transparent"}):
|
|
43
|
-
solara.HTML(tag="h2", unsafe_innerHTML=route.label, style={"color": "white", "padding": "1.5rem"})
|
|
44
|
-
with solara.Column(style={"justify-content": "center", "height": "100%", "background-color": "transparent"}):
|
|
24
|
+
if route_current.path == "documentation":
|
|
25
|
+
with solara.Column(style={"width": "100%", "max-width": "1024px"}, gap="40px"):
|
|
26
|
+
with solara.Column(style={"width": "100%", "align-items": "center"}, gap="40px"):
|
|
27
|
+
with solara.Column(gap="20px", classes=["docs-card-container"], style={"max-width": "80%", "padding-top": "64px"}, align="stretch"):
|
|
28
|
+
for route in route_current.children:
|
|
29
|
+
if route.path in ["/", "advanced", "faq"]:
|
|
30
|
+
continue
|
|
31
|
+
with solara.Link("/documentation/" + route.path):
|
|
32
|
+
with solara.Row(
|
|
33
|
+
classes=["docs-card"],
|
|
34
|
+
style={
|
|
35
|
+
"background-color": f"var({'--docs-color-grey' if route.path != 'getting_started' else '--color-primary'})",
|
|
36
|
+
"align-items": "center",
|
|
37
|
+
},
|
|
38
|
+
):
|
|
39
|
+
solara.HTML(tag="h2", unsafe_innerHTML=route.label, style={"color": "white", "display": "block", "flex-grow": "1"})
|
|
45
40
|
solara.v.Icon(children=["mdi-arrow-right"], color="var(--color-grey-light)", x_large=True, class_="docs-card-icon")
|
|
46
|
-
|
|
47
|
-
with solara.Column(style={"padding-left": "10%"}):
|
|
41
|
+
with solara.Column(gap="10px", style={"flex-wrap": "wrap", "max-width": "80%"}):
|
|
48
42
|
solara.HTML(tag="h2", unsafe_innerHTML="How to use our documentation:", style={"padding": "1.5rem"})
|
|
49
43
|
solara.Markdown(
|
|
50
44
|
"""
|
|
@@ -58,28 +52,23 @@ def Page(children=[]):
|
|
|
58
52
|
If a component you would like to use is not available in Solara, you can use the underlying library directly.
|
|
59
53
|
"""
|
|
60
54
|
)
|
|
61
|
-
with solara.Column(style={"justify-content": "center", "height": "100%"}):
|
|
62
55
|
solara.HTML(tag="h2", unsafe_innerHTML="Also Check Out", style={"padding": "1.5rem"})
|
|
63
|
-
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
|
|
56
|
+
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
|
|
64
57
|
with solara.v.Html(tag="a", attributes={"href": "https://discord.solara.dev", "target": "_blank"}):
|
|
65
58
|
with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-discord)"}):
|
|
66
59
|
solara.v.Html(tag="img", attributes={"src": "/static/public/social/discord.svg"}, style_="height: 1.5rem; width: auto;")
|
|
67
60
|
solara.Text("We use discord to provide support and answer questions there actively.")
|
|
68
|
-
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
|
|
61
|
+
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
|
|
69
62
|
with solara.v.Html(tag="a", attributes={"href": "https://github.com/widgetti/solara", "target": "_blank"}):
|
|
70
63
|
with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-github)"}):
|
|
71
64
|
solara.v.Html(tag="img", attributes={"src": "/static/public/social/github.svg"}, style_="height: 1.5rem; width: auto;")
|
|
72
65
|
solara.Text("Search for solutions on Github issues, or report bugs.")
|
|
73
|
-
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center"}):
|
|
66
|
+
with solara.Row(gap="20px", style={"flex-wrap": "wrap", "row-gap": "20px", "align-items": "center", "padding-left": "24px"}):
|
|
74
67
|
with solara.v.Html(tag="a", attributes={"href": "https://twitter.com/solara_dev", "target": "_blank"}):
|
|
75
68
|
with solara.Div(classes=["social-logo-container"], style={"background-color": "var(--docs-social-twitter)"}):
|
|
76
69
|
solara.v.Html(tag="img", attributes={"src": "/static/public/social/twitter.svg"}, style_="height: 1.5rem; width: auto;")
|
|
77
70
|
solara.Text("Get announcements about Solara features, showcases, and events!.")
|
|
78
71
|
|
|
79
|
-
else:
|
|
80
|
-
with solara.Column(align="center", children=children, style={"padding": "0"}):
|
|
81
|
-
pass
|
|
82
|
-
|
|
83
72
|
|
|
84
73
|
@solara.component
|
|
85
74
|
def Layout(children=[]):
|
|
@@ -90,7 +79,10 @@ def Layout(children=[]):
|
|
|
90
79
|
if route_current.path == "/":
|
|
91
80
|
return Page()
|
|
92
81
|
else:
|
|
93
|
-
|
|
82
|
+
with solara.Column(
|
|
83
|
+
align="center", children=children, style={"padding": "0 0 40px 0", "max-width": "90%"}
|
|
84
|
+
): # 40px bottom margin for "runs on Solara" text
|
|
85
|
+
pass
|
|
94
86
|
|
|
95
87
|
|
|
96
88
|
@solara.component
|
|
@@ -41,7 +41,8 @@ If you do not see your app, you can open the browser developer tools in your bro
|
|
|
41
41
|
|
|
42
42
|
### Security considerations
|
|
43
43
|
|
|
44
|
-
Solara uses a cookie to implement sessions. To support cookies
|
|
44
|
+
Solara uses a cookie to implement sessions. To support setting cookies in an iframe, we set the session cookie using `Secure`, and `SameSite=Strict`. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies) for more details. This means that we can only support iframes via https or localhost. Note that proxy servers can tell
|
|
45
|
+
solara-server that the connection is secure by forwarding the `X-Forwarded-Proto` header, see [our self hosted deployment documentation for more information](https://solara.dev/documentation/getting_started/deploying/self-hosted).
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
## Embed into an existing page
|
|
@@ -6,7 +6,7 @@ description: Solara looks for overrides of certain style and asset files in the
|
|
|
6
6
|
|
|
7
7
|
Asset files are special files with are loaded by Solara-server and thus have a special meaning, and come with defaults. Current supported assets files are:
|
|
8
8
|
|
|
9
|
-
* `favicon.png` - Image shown by the browser (usually in the tab).
|
|
9
|
+
* `favicon.png` and/or `favicon.svg` - Image shown by the browser (usually in the tab). If SVG is not provided, default `favicon.svg` of the solara server may override your custom favicon.png depending on the browser. Providing both PNG and SVG versions is recommended.
|
|
10
10
|
* `style.css` - Default `CSS` used by Solara.
|
|
11
11
|
* `custom.css` - Custom `CSS` you can override for your project (empty `CSS` file by default).
|
|
12
12
|
* `custom.js` - Custom Javascript you can use for your project (empty Javascript file by default).
|
|
@@ -196,7 +196,7 @@ Note that all routes are relative, since a component does not know if it is embe
|
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
Therefore you should never use the `route.path` for navigation since the route object has no knowledge of the full url
|
|
199
|
-
(e.g. `/docs/basics/
|
|
199
|
+
(e.g. `/docs/basics/ipywidgets`) but only knows its small piece of the pathname (e.g. `ipywidgets`)
|
|
200
200
|
|
|
201
201
|
Using [`resolve_path`](/documentation/api/routing/resolve_path) we can request the full url for navigation.
|
|
202
202
|
|
|
@@ -219,6 +219,22 @@ def LinkToIpywidgets():
|
|
|
219
219
|
return main
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
+
### Linking to Sections of a Page
|
|
223
|
+
|
|
224
|
+
The `solara.Link` component also supports linking to HTML elements identified by id. Although most Solara components don't directly support the id attribute, you can assign ids to all ipyvuetify components, using the `attributes` argument:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
solara.v.Btn(attributes={"id": "my-id"}, ...)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
You can then link to a particular element by appending `#` followed by its id to your link, i.e. `solara.Link(route_or_path="/page#my-id")`. If you want the page to smoothly scroll to the linked element, you should give an element that contains it (for instance the `html`-element) the following CSS rule:
|
|
231
|
+
|
|
232
|
+
```css
|
|
233
|
+
html {
|
|
234
|
+
scroll-behaviour: smooth;
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
222
238
|
## Fully manual routing
|
|
223
239
|
|
|
224
240
|
If you want to do routing fully manually, you can use the [`solara.use_router`](/documentation/api/routing/use_router) hook, and use the `.path` attribute.
|
|
@@ -38,7 +38,8 @@ Each virtual kernel runs in its own thread, this ensures that one particular use
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
## Handling Multiple Workers
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
In setups with multiple workers, it's possible for a page to (re)connect to a different worker than its original. This can happen after a lost network connection is restored, or when [ipypopout](https://github.com/widgetti/ipypopout) is used, since ipypopout creates a new connection, which can end up at a different worker. This can result in a loss of the virtual kernel, since it lives on the worker that was first connected to. The Solara app will then initiate a fresh start, or simply fail when ipypopout is used. To prevent this scenario, a sticky session configuration is recommended, ensuring consistent client-worker connections. A load balancer, such as [nginx](https://www.nginx.com/), can be used to achieve this. Note that using multiple workers (e.g. by using gunicorn) cannot work since a connection will be made to a different worker each time.
|
|
42
43
|
|
|
43
44
|
If you have questions about setting this up, or require assistance, please [contact us](https://solara.dev/docs/contact).
|
|
44
45
|
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Solara enterprise is a not Open Source, but the source code is visible, is free for non-commercial use and installable from pypi.
|
|
4
4
|
|
|
5
|
-
For commercial use, you require a license. Please [
|
|
5
|
+
For commercial use, you require a license. Please see [pricing](/pricing) for more information.
|
|
6
6
|
|
|
7
7
|
Solara-enterprise will stay free for non-commercial use and features that are in solara will **not be moved to solara-enterprise**.
|
|
@@ -44,12 +44,15 @@ from solara_enterprise import auth
|
|
|
44
44
|
@solara.component
|
|
45
45
|
def Page():
|
|
46
46
|
if not auth.user.value:
|
|
47
|
-
|
|
47
|
+
# `get_login_url` should automatically redirect the user back to the current page.
|
|
48
|
+
# The URL argument is only used here as an example.
|
|
49
|
+
solara.Button("Login", icon_name="mdi-login", href=auth.get_login_url("documentation/advanced/enterprise/oauth"))
|
|
48
50
|
else:
|
|
49
51
|
userinfo = auth.user.value['userinfo']
|
|
50
52
|
if 'name' in userinfo:
|
|
51
53
|
solara.Markdown(f"### Welcome {userinfo['name']}")
|
|
52
|
-
|
|
54
|
+
# See above comment
|
|
55
|
+
solara.Button("Logout", icon_name="mdi-logout", href=auth.get_logout_url("documentation/advanced/enterprise/oauth"))
|
|
53
56
|
```
|
|
54
57
|
## How to configure OAuth
|
|
55
58
|
|
|
@@ -56,3 +56,9 @@ graph TD;
|
|
|
56
56
|
RUNNING-- "work finished" -->FINISHED
|
|
57
57
|
RUNNING-- "cancel()" -->CANCELLED
|
|
58
58
|
```
|
|
59
|
+
|
|
60
|
+
## Future deprecation
|
|
61
|
+
|
|
62
|
+
Note that [`use_task`](/https://solara.dev/documentation/components/lab/use_task) is an alternative to `use_thread` that will most likely
|
|
63
|
+
replace `use_thread` in the future. Compared to `use_thread`, `use_task` has no intrusive cancel, which turned out to be too large of
|
|
64
|
+
a performance overhead to be useful. Also, `use_task` can run async functions, which is not possible with `use_thread`.
|
|
@@ -54,10 +54,10 @@ def Page():
|
|
|
54
54
|
return solara.Markdown("This example requires vaex, please install it with `pip install vaex`")
|
|
55
55
|
with solara.Div() as main:
|
|
56
56
|
solara.Markdown("# Titanic")
|
|
57
|
-
selected, on_selected = solara.use_state({"x": [0, 0]})
|
|
57
|
+
selected, on_selected = solara.use_state({"x": [0, 0]}) # noqa: SH101
|
|
58
58
|
solara.provide_cross_filter()
|
|
59
59
|
with solara.VBox():
|
|
60
|
-
type, set_type = solara.use_state("view")
|
|
60
|
+
type, set_type = solara.use_state("view") # noqa: SH101
|
|
61
61
|
with solara.ToggleButtonsSingle(type, on_value=set_type):
|
|
62
62
|
solara.Button("PivotTableView", value="view")
|
|
63
63
|
solara.Button("PivotTable", value="df")
|
|
@@ -13,6 +13,8 @@ Page = NoPage
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
__doc__ += apidoc(solara.InputText.f) # type: ignore
|
|
16
|
+
__doc__ += "# InputTextArea"
|
|
17
|
+
__doc__ += apidoc(solara.InputTextArea.f) # type: ignore
|
|
16
18
|
__doc__ += "# InputFloat"
|
|
17
19
|
__doc__ += apidoc(solara.InputFloat.f) # type: ignore
|
|
18
20
|
__doc__ += "# InputInt"
|
|
@@ -42,8 +42,8 @@ if vaex is not None:
|
|
|
42
42
|
def Page():
|
|
43
43
|
if vaex is None:
|
|
44
44
|
return solara.Error("Vaex is not installed, run pip install vaex-core vaex-hdf5")
|
|
45
|
-
query, set_query = solara.use_state("SELECT * from titanic")
|
|
46
|
-
query_executed, set_query_executed = solara.use_state(cast(Optional[str], None))
|
|
45
|
+
query, set_query = solara.use_state("SELECT * from titanic") # noqa: SH101
|
|
46
|
+
query_executed, set_query_executed = solara.use_state(cast(Optional[str], None)) # noqa: SH101
|
|
47
47
|
|
|
48
48
|
def run_query(cancel: threading.Event) -> pd.DataFrame:
|
|
49
49
|
if not query_executed:
|
|
@@ -55,7 +55,7 @@ def Page():
|
|
|
55
55
|
df = pd.DataFrame(cursor.fetchall(), columns=[k[0] for k in cursor.description])
|
|
56
56
|
return df
|
|
57
57
|
|
|
58
|
-
result: solara.Result[pd.DataFrame] = solara.use_thread(run_query, dependencies=[query_executed])
|
|
58
|
+
result: solara.Result[pd.DataFrame] = solara.use_thread(run_query, dependencies=[query_executed]) # noqa: SH101
|
|
59
59
|
with solara.VBox() as main:
|
|
60
60
|
solara.SqlCode(query=query, tables=table_hints, on_query=set_query)
|
|
61
61
|
enable_execute = (query != query_executed) or result.error is not None
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import solara
|
|
2
|
-
from solara.website.components import Gallery
|
|
2
|
+
from solara.website.components import Gallery, MarkdownWithMetadata
|
|
3
3
|
|
|
4
4
|
title = "Examples"
|
|
5
5
|
|
|
@@ -25,28 +25,20 @@ def Layout(children):
|
|
|
25
25
|
assert module is not None
|
|
26
26
|
github_url = solara.util.github_url(module.__file__)
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
solara.Button("View source code on GitHub", icon_name="mdi-github-circle", href=github_url, class_="ma-2", target="_blank", text=True)
|
|
41
|
-
# code = inspect.getsource(module)
|
|
42
|
-
|
|
43
|
-
# code_quoted = urllib.parse.quote_plus(code)
|
|
44
|
-
# url = f"https://test.solara.dev/try?code={code_quoted}"
|
|
45
|
-
# solara.Button("Run on solara.dev", icon_name="mdi-pencil", href=url, class_="ma-2", target="_blank")
|
|
46
|
-
# with solara.HBox():
|
|
28
|
+
if route_current.path == "fullscreen":
|
|
29
|
+
with solara.Padding(4, children=children):
|
|
30
|
+
pass
|
|
31
|
+
else:
|
|
32
|
+
with solara.Column(align="center", style={"max-width": "100%"}):
|
|
33
|
+
doc = module.__doc__
|
|
34
|
+
if doc:
|
|
35
|
+
with solara.Column():
|
|
36
|
+
MarkdownWithMetadata(doc)
|
|
37
|
+
with solara.Column(style={"max-width": "min(100%, 1024px)", "width": "100%"}):
|
|
38
|
+
if route_current.path != "/":
|
|
39
|
+
solara.Button("View source code on GitHub", icon_name="mdi-github-circle", href=github_url, class_="ma-2", target="_blank", text=True)
|
|
47
40
|
if not hasattr(module, "Page"):
|
|
48
41
|
solara.Error(f"No Page component found in {module}")
|
|
49
42
|
else:
|
|
50
|
-
with solara.
|
|
43
|
+
with solara.Div(children=children):
|
|
51
44
|
pass
|
|
52
|
-
return main
|
|
@@ -77,7 +77,7 @@ def Page():
|
|
|
77
77
|
task = solara.lab.use_task(call_openai, dependencies=[user_message_count]) # type: ignore
|
|
78
78
|
|
|
79
79
|
with solara.Column(
|
|
80
|
-
style={"width": "
|
|
80
|
+
style={"width": "100%", "height": "50vh"},
|
|
81
81
|
):
|
|
82
82
|
with solara.lab.ChatBox():
|
|
83
83
|
for item in messages.value:
|
|
@@ -35,7 +35,7 @@ def Page():
|
|
|
35
35
|
sales_data = np.floor(np.cumsum(gen.random(7) - 0.5) * 100 + 100)
|
|
36
36
|
show_report = solara.use_reactive(False)
|
|
37
37
|
|
|
38
|
-
with solara.Column(
|
|
38
|
+
with solara.Column():
|
|
39
39
|
if show_report.value:
|
|
40
40
|
with solara.Card("Report"):
|
|
41
41
|
solara.Markdown("Lorum ipsum dolor sit amet")
|
|
@@ -34,6 +34,6 @@ def Page(x=x0, ymax=5):
|
|
|
34
34
|
lines = bqplot.Lines(x=x, y=y, scales={"x": x_scale, "y": y_scale}, stroke_width=3, colors=[color], display_legend=display_legend, labels=[label])
|
|
35
35
|
x_axis = bqplot.Axis(scale=x_scale)
|
|
36
36
|
y_axis = bqplot.Axis(scale=y_scale, orientation="vertical")
|
|
37
|
-
bqplot.Figure(axes=[x_axis, y_axis], marks=[lines], scale_x=x_scale, scale_y=y_scale, layout={"
|
|
37
|
+
bqplot.Figure(axes=[x_axis, y_axis], marks=[lines], scale_x=x_scale, scale_y=y_scale, layout={"max_width": "100%", "width": "100%"})
|
|
38
38
|
|
|
39
39
|
# return main
|
|
@@ -15,7 +15,7 @@ bounds = solara.reactive(None)
|
|
|
15
15
|
@solara.component
|
|
16
16
|
def Page():
|
|
17
17
|
# Isolation is required to prevent the map from overlapping navigation (when screen width < 960px)
|
|
18
|
-
with solara.Column(style={"
|
|
18
|
+
with solara.Column(style={"width": "100%", "height": "500px", "isolation": "isolate"}):
|
|
19
19
|
# solara components support reactive variables
|
|
20
20
|
solara.SliderInt(label="Zoom level", value=zoom, min=1, max=20)
|
|
21
21
|
# using 3rd party widget library require wiring up the events manually
|
|
@@ -31,7 +31,7 @@ def Page():
|
|
|
31
31
|
# do things with the location
|
|
32
32
|
marker_location.set(location)
|
|
33
33
|
|
|
34
|
-
with solara.Column(style={"
|
|
34
|
+
with solara.Column(style={"width": "100%", "height": "500px"}):
|
|
35
35
|
solara.Markdown(f"Market set to: {marker_location.value}", style={"color": "#6e6e6e"})
|
|
36
36
|
|
|
37
37
|
map = maps[map_name.value]
|
|
@@ -9,7 +9,6 @@ The UI code demonstrates a lot of conditional rendering.
|
|
|
9
9
|
import time
|
|
10
10
|
|
|
11
11
|
import solara
|
|
12
|
-
from solara.alias import rv
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
@solara.component
|
|
@@ -41,24 +40,23 @@ def Page():
|
|
|
41
40
|
|
|
42
41
|
solara.use_thread(run_timer, dependencies=[duration, running])
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
solara.Error("Duration must be at least 1 second")
|
|
48
|
-
else:
|
|
49
|
-
solara.Markdown(f"# Timer set to {seconds} seconds")
|
|
43
|
+
if not running:
|
|
44
|
+
if duration < 1:
|
|
45
|
+
solara.Error("Duration must be at least 1 second")
|
|
50
46
|
else:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
solara.Markdown(f"# Timer set to {seconds} seconds")
|
|
48
|
+
else:
|
|
49
|
+
if seconds:
|
|
50
|
+
solara.Markdown(f"# {seconds} seconds left")
|
|
51
|
+
else:
|
|
52
|
+
solara.solara.Markdown("# Time's up!")
|
|
53
|
+
|
|
54
|
+
solara.v.TextField(type="number", v_model=duration, on_v_model=on_duration, disabled=running)
|
|
55
|
+
with solara.Row():
|
|
56
|
+
if running:
|
|
57
|
+
solara.Button("Stop", on_click=lambda: set_running(False), icon_name="mdi-stop")
|
|
58
|
+
else:
|
|
59
|
+
if duration != seconds:
|
|
60
|
+
solara.Button("Reset", on_click=lambda: set_seconds(duration), icon_name="mdi-restart")
|
|
59
61
|
else:
|
|
60
|
-
|
|
61
|
-
solara.Button("Reset", on_click=lambda: set_seconds(duration), icon_name="mdi-restart")
|
|
62
|
-
else:
|
|
63
|
-
solara.Button("Start", on_click=lambda: set_running(True), icon_name="mdi-play", disabled=seconds < 1)
|
|
64
|
-
return main
|
|
62
|
+
solara.Button("Start", on_click=lambda: set_running(True), icon_name="mdi-play", disabled=seconds < 1)
|
|
@@ -49,8 +49,8 @@ def ClickScatter(df, x, y, color, click_row, on_click: Callable[[ClickPoint], No
|
|
|
49
49
|
click_y = df[y].values[click_row]
|
|
50
50
|
fig.add_trace(px.scatter(x=[click_x], y=[click_y], text=["⭐️"]).data[0])
|
|
51
51
|
# make the figure a bit smaller
|
|
52
|
-
fig.update_layout(width=
|
|
53
|
-
with solara.
|
|
52
|
+
fig.update_layout(width=340)
|
|
53
|
+
with solara.Column(style={"width": "340px"}) as main:
|
|
54
54
|
solara.FigurePlotly(fig, on_click=on_click_trace)
|
|
55
55
|
solara.Select(label="X-axis", value=x, values=columns, on_value=set_x)
|
|
56
56
|
solara.Select(label="Y-axis", value=y, values=columns, on_value=set_y)
|
|
@@ -65,8 +65,8 @@ def Page():
|
|
|
65
65
|
else:
|
|
66
66
|
clicked_row = None
|
|
67
67
|
|
|
68
|
-
with solara.
|
|
69
|
-
with solara.
|
|
68
|
+
with solara.Column() as main:
|
|
69
|
+
with solara.Row(justify="center", style={"flex-wrap": "wrap"}):
|
|
70
70
|
ClickScatter(df, "sepal_length", "sepal_width", "species", clicked_row, on_click=set_click_point)
|
|
71
71
|
ClickScatter(df, "petal_length", "petal_width", "species", clicked_row, on_click=set_click_point)
|
|
72
72
|
if click_point is not None:
|
|
@@ -87,3 +87,21 @@ In case you forgot how to start a notebook server:
|
|
|
87
87
|
Or the more modern Jupyter lab:
|
|
88
88
|
|
|
89
89
|
$ jupyter lab
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Run as app (experimental)
|
|
93
|
+
|
|
94
|
+
You can also run the script as a standalone app. This requires the extra packages `qtpy` and `PySide6` (or `PyQt6`) to be installed.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
$ pip install pip install qtpy PySide6
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Run from the command line in the same directory where you put your file (`sol.py`):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
$ solara run sol.py --qt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
<img src="https://dxhl76zpt6fap.cloudfront.net/public/solara-quickstart-app.webp" alt="Markdown Monster icon"/>
|
solara/website/pages/documentation/getting_started/content/04-tutorials/_jupyter_dashboard_1.ipynb
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"\n",
|
|
36
36
|
"We will use a subsample of the [San Fanfrisco crime dataset](https://www.kaggle.com/competitions/sf-crime/data) which contains information on types of crimes and where they were committed.\n",
|
|
37
37
|
"\n",
|
|
38
|
-
"[Download the CSV file](https://
|
|
38
|
+
"[Download the CSV file](https://github.com/widgetti/solara/raw/master/solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz) if you want to run this locally, or let the code below sort it out."
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
41
|
{
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
"\n",
|
|
351
351
|
"ROOT = Path(solara.__file__).parent / \"website\" / \"pages\" / \"docs\" / \"content\" / \"04-tutorial\"\n",
|
|
352
352
|
"path = ROOT / Path(\"SF_crime_sample.csv.gz\")\n",
|
|
353
|
-
"url = \"https://
|
|
353
|
+
"url = \"https://github.com/widgetti/solara/raw/master/solara/website/pages/documentation/getting_started/content/04-tutorials/SF_crime_sample.csv.gz\"\n",
|
|
354
354
|
"\n",
|
|
355
355
|
"if path.exists():\n",
|
|
356
356
|
" df_crime = pd.read_csv(path)\n",
|