solara-ui 1.31.0__py2.py3-none-any.whl → 1.32.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/components/applayout.py +6 -2
- solara/components/datatable.py +5 -12
- solara/lab/hooks/dataframe.py +1 -12
- solara/lab/utils/dataframe.py +40 -0
- solara/minisettings.py +13 -5
- solara/server/flask.py +3 -5
- solara/server/kernel_context.py +110 -60
- solara/server/server.py +8 -4
- solara/server/settings.py +23 -1
- solara/server/starlette.py +4 -5
- solara/server/static/main-vuetify.js +3 -1
- solara/server/static/solara_bootstrap.py +1 -1
- solara/tasks.py +19 -10
- solara/toestand.py +22 -13
- solara/website/assets/custom.css +13 -0
- solara/website/components/algolia.py +6 -0
- solara/website/components/algolia_api.vue +2 -1
- solara/website/components/header.py +9 -17
- solara/website/components/sidebar.py +91 -0
- solara/website/pages/__init__.py +25 -67
- solara/website/pages/changelog/__init__.py +2 -0
- solara/website/pages/changelog/changelog.md +12 -0
- solara/website/pages/contact/__init__.py +2 -0
- solara/website/pages/documentation/__init__.py +2 -88
- solara/website/pages/documentation/advanced/content/10-howto/30-testing.md +267 -16
- solara/website/pages/documentation/advanced/content/15-reference/41-asset-files.md +36 -0
- solara/website/pages/documentation/advanced/content/30-enterprise/10-oauth.md +11 -2
- solara/website/pages/documentation/advanced/content/40-development/10-setup.md +1 -1
- solara/website/pages/documentation/faq/content/99-faq.md +27 -0
- solara/website/pages/documentation/getting_started/content/02-installing.md +2 -2
- solara/website/pages/documentation/getting_started/content/07-deploying/10-self-hosted.md +20 -4
- {solara_ui-1.31.0.dist-info → solara_ui-1.32.0.dist-info}/METADATA +2 -2
- {solara_ui-1.31.0.dist-info → solara_ui-1.32.0.dist-info}/RECORD +38 -36
- {solara_ui-1.31.0.data → solara_ui-1.32.0.data}/data/etc/jupyter/jupyter_notebook_config.d/solara.json +0 -0
- {solara_ui-1.31.0.data → solara_ui-1.32.0.data}/data/etc/jupyter/jupyter_server_config.d/solara.json +0 -0
- {solara_ui-1.31.0.dist-info → solara_ui-1.32.0.dist-info}/WHEEL +0 -0
- {solara_ui-1.31.0.dist-info → solara_ui-1.32.0.dist-info}/licenses/LICENSE +0 -0
solara/toestand.py
CHANGED
|
@@ -77,7 +77,12 @@ def merge_state(d1: S, **kwargs) -> S:
|
|
|
77
77
|
if dataclasses.is_dataclass(d1):
|
|
78
78
|
return dataclasses.replace(d1, **kwargs) # type: ignore
|
|
79
79
|
if "pydantic" in sys.modules and isinstance(d1, sys.modules["pydantic"].BaseModel):
|
|
80
|
-
|
|
80
|
+
module = sys.modules["pydantic"]
|
|
81
|
+
version_major = int(module.__version__.split(".")[0])
|
|
82
|
+
if version_major >= 2:
|
|
83
|
+
return d1.model_copy(update=kwargs)
|
|
84
|
+
else:
|
|
85
|
+
return d1.copy(update=kwargs)
|
|
81
86
|
return cast(S, {**cast(dict, d1), **kwargs})
|
|
82
87
|
|
|
83
88
|
|
|
@@ -282,21 +287,25 @@ class KernelStoreValue(KernelStore[S]):
|
|
|
282
287
|
return self.default_value
|
|
283
288
|
|
|
284
289
|
|
|
290
|
+
def _create_key_callable(f: Callable[[], S]):
|
|
291
|
+
try:
|
|
292
|
+
prefix = f.__qualname__
|
|
293
|
+
except Exception:
|
|
294
|
+
prefix = repr(f)
|
|
295
|
+
with KernelStore.scope_lock:
|
|
296
|
+
index = KernelStore._type_counter[prefix]
|
|
297
|
+
KernelStore._type_counter[prefix] += 1
|
|
298
|
+
try:
|
|
299
|
+
key = f.__module__ + ":" + prefix + ":" + str(index)
|
|
300
|
+
except Exception:
|
|
301
|
+
key = prefix + ":" + str(index)
|
|
302
|
+
return key
|
|
303
|
+
|
|
304
|
+
|
|
285
305
|
class KernelStoreFactory(KernelStore[S]):
|
|
286
306
|
def __init__(self, factory: Callable[[], S], key=None):
|
|
287
307
|
self.factory = factory
|
|
288
|
-
|
|
289
|
-
prefix = factory.__qualname__
|
|
290
|
-
except Exception:
|
|
291
|
-
prefix = repr(factory)
|
|
292
|
-
if key is None:
|
|
293
|
-
with KernelStore.scope_lock:
|
|
294
|
-
index = self._type_counter[prefix]
|
|
295
|
-
self._type_counter[prefix] += 1
|
|
296
|
-
try:
|
|
297
|
-
key = factory.__module__ + ":" + prefix + ":" + str(index)
|
|
298
|
-
except Exception:
|
|
299
|
-
key = prefix + ":" + str(index)
|
|
308
|
+
key = key or _create_key_callable(factory)
|
|
300
309
|
super().__init__(key=key)
|
|
301
310
|
|
|
302
311
|
def initial_value(self) -> S:
|
solara/website/assets/custom.css
CHANGED
|
@@ -239,6 +239,16 @@ blockquote p:last-child {
|
|
|
239
239
|
border-radius: 8px;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
.v-navigation-drawer__content .algolia {
|
|
243
|
+
padding: 0.35rem;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@media screen and (max-width: 960px) {
|
|
247
|
+
.header-logo-container{
|
|
248
|
+
justify-content: center !important;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
242
252
|
/* vuetify component overrides */
|
|
243
253
|
|
|
244
254
|
.v-btn.solara-docs-button {
|
|
@@ -262,6 +272,9 @@ blockquote p:last-child {
|
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
/* header */
|
|
275
|
+
.header-logo {
|
|
276
|
+
display: block;
|
|
277
|
+
}
|
|
265
278
|
.news {
|
|
266
279
|
background-color: var(--color-primary);
|
|
267
280
|
padding: 10px;
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
rounded
|
|
13
13
|
clearable
|
|
14
14
|
ref="search"
|
|
15
|
-
style="
|
|
15
|
+
style="flex-grow: 1; max-width: 650px;"
|
|
16
16
|
@click="show($event, on);"
|
|
17
17
|
@keyup.enter="item = 0"
|
|
18
|
+
class="algolia"
|
|
18
19
|
></v-text-field>
|
|
19
20
|
</template>
|
|
20
21
|
<v-list v-if="results != null && results.length == 0">
|
|
@@ -4,11 +4,7 @@ import solara
|
|
|
4
4
|
import solara.lab
|
|
5
5
|
from solara.alias import rv
|
|
6
6
|
from solara.server import settings
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@solara.component_vue("algolia_api.vue")
|
|
10
|
-
def Algolia():
|
|
11
|
-
pass
|
|
7
|
+
from .algolia import Algolia
|
|
12
8
|
|
|
13
9
|
|
|
14
10
|
@solara.component
|
|
@@ -31,21 +27,17 @@ def Header(
|
|
|
31
27
|
)
|
|
32
28
|
with solara.v.AppBar(tag="header", flat=True, class_="bg-primary-fade padding-40", height="auto", clipped_left=True):
|
|
33
29
|
with rv.ToolbarTitle(class_="d-flex", style_="align-items:center"):
|
|
34
|
-
if route_current and
|
|
30
|
+
if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
|
|
35
31
|
with solara.Button(icon=True, class_="hidden-md-and-up", on_click=lambda: on_toggle_left_menu and on_toggle_left_menu()):
|
|
36
32
|
rv.Icon(children=["mdi-menu"])
|
|
37
|
-
with solara.Link(path_or_route="/"):
|
|
38
|
-
solara.Image(router.root_path + f"/static/assets/images/logo{'_white' if dark_effective else ''}.svg")
|
|
39
|
-
rv.Spacer()
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
and route_current is not None
|
|
44
|
-
and route_current.path == "documentation"
|
|
45
|
-
and route_current_with_children.path == "/"
|
|
34
|
+
with solara.Row(
|
|
35
|
+
justify="start", classes=["header-logo-container"], style={"flex-grow": "1", "background-color": "transparent", "align-items": "center"}
|
|
46
36
|
):
|
|
47
|
-
solara.
|
|
48
|
-
|
|
37
|
+
with solara.Link(path_or_route="/"):
|
|
38
|
+
solara.Image(router.root_path + f"/static/assets/images/logo{'_white' if dark_effective else ''}.svg", classes=["header-logo"])
|
|
39
|
+
|
|
40
|
+
with rv.Html(tag="ul", class_="main-menu menu d-none d-md-flex", style_="flex-grow: 1;"):
|
|
49
41
|
if settings.search.enabled:
|
|
50
42
|
from solara_enterprise.search.search import Search
|
|
51
43
|
|
|
@@ -53,7 +45,7 @@ def Header(
|
|
|
53
45
|
else:
|
|
54
46
|
with solara.Row(justify="end", style={"align-items": "center", "flex-grow": "1", "background-color": "transparent"}):
|
|
55
47
|
Algolia()
|
|
56
|
-
|
|
48
|
+
|
|
57
49
|
for route in all_routes:
|
|
58
50
|
if route.path in ["apps", "contact", "changelog"]:
|
|
59
51
|
continue
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import solara
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@solara.component
|
|
5
|
+
def Sidebar():
|
|
6
|
+
route_current, all_routes = solara.use_route(-1)
|
|
7
|
+
router = solara.use_router()
|
|
8
|
+
if route_current is None:
|
|
9
|
+
return solara.Error("Page not found")
|
|
10
|
+
|
|
11
|
+
# Pick out documentation route, so we can use this on any page
|
|
12
|
+
for route in all_routes:
|
|
13
|
+
if route.path == "documentation":
|
|
14
|
+
all_routes = route.children
|
|
15
|
+
break
|
|
16
|
+
|
|
17
|
+
with solara.v.List(expand=True, nav=True, style_="height: 100%; display: flex; flex-direction: column;") as main:
|
|
18
|
+
with solara.v.ListItemGroup(v_model=router.path):
|
|
19
|
+
for route in all_routes:
|
|
20
|
+
if len(route.children) == 1 or route.path == "/":
|
|
21
|
+
with solara.Link("/documentation/" + route.path if route.path != "/" else "/documentation"):
|
|
22
|
+
with solara.v.ListItem(value="/documentation/" + route.path if route.path != "/" else "/documentation"):
|
|
23
|
+
if route.path == "/":
|
|
24
|
+
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-home"])])
|
|
25
|
+
solara.v.ListItemTitle(style_="padding: 0 20px;", children=[route.label])
|
|
26
|
+
else:
|
|
27
|
+
with solara.v.ListGroup(
|
|
28
|
+
v_slots=[
|
|
29
|
+
{
|
|
30
|
+
"name": "activator",
|
|
31
|
+
"children": solara.v.ListItemTitle(
|
|
32
|
+
children=[route.label],
|
|
33
|
+
style_="padding: 0 20px;",
|
|
34
|
+
),
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
value=router.path.startswith("/documentation/" + route.path),
|
|
38
|
+
):
|
|
39
|
+
for item in route.children:
|
|
40
|
+
if item.path == "/":
|
|
41
|
+
continue
|
|
42
|
+
if item.children != [] and any([c.label is not None and c.path != "/" for c in item.children]):
|
|
43
|
+
with solara.v.ListGroup(
|
|
44
|
+
v_slots=[
|
|
45
|
+
{
|
|
46
|
+
"name": "activator",
|
|
47
|
+
"children": solara.v.ListItemTitle(
|
|
48
|
+
children=[item.label],
|
|
49
|
+
),
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
sub_group=True,
|
|
53
|
+
no_action=True,
|
|
54
|
+
value=router.path.startswith("/documentation/" + route.path + "/" + item.path),
|
|
55
|
+
):
|
|
56
|
+
for subitem in item.children:
|
|
57
|
+
# skip pages that are only used to demonstrate Link or Router usage
|
|
58
|
+
if subitem.path == "/" or subitem.label is None:
|
|
59
|
+
continue
|
|
60
|
+
path = (
|
|
61
|
+
"/documentation/" + route.path + "/" + item.path + "/" + subitem.path
|
|
62
|
+
if item.path != "fullscreen"
|
|
63
|
+
else "/apps/" + subitem.path
|
|
64
|
+
)
|
|
65
|
+
with solara.Link(
|
|
66
|
+
path,
|
|
67
|
+
):
|
|
68
|
+
with solara.v.ListItem(dense=True, style_="padding: 0 20px;", value=path):
|
|
69
|
+
solara.v.ListItemContent(
|
|
70
|
+
children=[subitem.label],
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
with solara.v.ListItemGroup(value="/documentation/" + route.path + "/" + item.path):
|
|
74
|
+
with solara.Link(
|
|
75
|
+
"/documentation/" + route.path + "/" + item.path,
|
|
76
|
+
):
|
|
77
|
+
with solara.v.ListItem(dense=True, style_="padding: 0 20px;"):
|
|
78
|
+
solara.v.ListItemContent(
|
|
79
|
+
children=[item.label],
|
|
80
|
+
)
|
|
81
|
+
with solara.v.ListItemGroup():
|
|
82
|
+
with solara.Link("/contact"):
|
|
83
|
+
with solara.v.ListItem():
|
|
84
|
+
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-email"])])
|
|
85
|
+
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Contact"])
|
|
86
|
+
with solara.Link("/changelog"):
|
|
87
|
+
with solara.v.ListItem():
|
|
88
|
+
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-history"])])
|
|
89
|
+
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Changelog"])
|
|
90
|
+
|
|
91
|
+
return main
|
solara/website/pages/__init__.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import contextlib
|
|
2
|
-
|
|
3
1
|
import solara
|
|
4
2
|
from solara import autorouting
|
|
5
3
|
from solara.alias import rv
|
|
6
4
|
from solara.components.title import Title
|
|
7
5
|
from solara.server import server
|
|
6
|
+
from solara.website.components.algolia import Algolia
|
|
8
7
|
|
|
9
8
|
from ..components import Header, Hero
|
|
10
9
|
from ..components.mailchimp import MailChimp
|
|
@@ -237,39 +236,6 @@ def List(children=[], class_: str = None):
|
|
|
237
236
|
return rv.Html(tag="ul", children=children, attributes={"class": class_})
|
|
238
237
|
|
|
239
238
|
|
|
240
|
-
@solara.component
|
|
241
|
-
def Sidebar():
|
|
242
|
-
route_current, all_routes = solara.use_route()
|
|
243
|
-
router = solara.use_router()
|
|
244
|
-
selected = router.path
|
|
245
|
-
with rv.Col(tag="aside", md=4, lg=3, class_="sidebar bg-grey d-none d-md-block") as main:
|
|
246
|
-
with List():
|
|
247
|
-
for route in all_routes:
|
|
248
|
-
if route.children and route.data is None:
|
|
249
|
-
path = solara.resolve_path(route.children[0])
|
|
250
|
-
path = getattr(route.module, "redirect", path)
|
|
251
|
-
path = getattr(route.children[0].module, "redirect", path)
|
|
252
|
-
with solara.Link(path) if path is not None else contextlib.nullcontext():
|
|
253
|
-
with SimpleListItem(route.label, class_="active" if path == selected else None):
|
|
254
|
-
with List():
|
|
255
|
-
for child in route.children[1:]:
|
|
256
|
-
path = solara.resolve_path(child)
|
|
257
|
-
path = getattr(child.module, "redirect", path)
|
|
258
|
-
with solara.Link(path) if path is not None else contextlib.nullcontext():
|
|
259
|
-
title = child.label or "no label"
|
|
260
|
-
if callable(title):
|
|
261
|
-
title = "Error: dynamic title"
|
|
262
|
-
SimpleListItem(title, class_="active" if path == selected else None)
|
|
263
|
-
else:
|
|
264
|
-
path = solara.resolve_path(route)
|
|
265
|
-
path = getattr(route.module, "redirect", path)
|
|
266
|
-
if route.children:
|
|
267
|
-
path = getattr(route.children[0].module, "redirect", path)
|
|
268
|
-
with solara.Link(path) if path is not None else contextlib.nullcontext():
|
|
269
|
-
SimpleListItem(route.label, class_="active" if path == selected else None)
|
|
270
|
-
return main
|
|
271
|
-
|
|
272
|
-
|
|
273
239
|
@solara.component
|
|
274
240
|
def Layout(children=[]):
|
|
275
241
|
router = solara.use_router()
|
|
@@ -476,17 +442,22 @@ def Layout(children=[]):
|
|
|
476
442
|
style_="flex-wrap: nowrap; margin: 0; min-height: calc(100vh - 215.5px);",
|
|
477
443
|
justify="center" if route_current is not None and route_current.path in ["documentation", "showcase"] else "start",
|
|
478
444
|
):
|
|
479
|
-
if route_current is not None and hasattr(route_current.module, "Sidebar"):
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
445
|
+
if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
|
|
446
|
+
with solara.v.NavigationDrawer(
|
|
447
|
+
clipped=True,
|
|
448
|
+
class_="d-none d-md-block",
|
|
449
|
+
height="unset",
|
|
450
|
+
style_="min-height: calc(100vh - 215.5px);",
|
|
451
|
+
width="20rem",
|
|
452
|
+
v_model=True, # Forces menu to display even if it had somehow been closed
|
|
453
|
+
):
|
|
454
|
+
route_current.module.Sidebar()
|
|
484
455
|
with rv.Col(
|
|
485
456
|
tag="main",
|
|
486
457
|
md=True,
|
|
487
458
|
class_="pa-0",
|
|
488
459
|
style_=f"""max-width: {'1024px' if route_current.path not in ['documentation', 'contact', 'changelog']
|
|
489
|
-
else 'unset'}; overflow: hidden
|
|
460
|
+
else 'unset'}; overflow-x: hidden;""",
|
|
490
461
|
):
|
|
491
462
|
if route_current is not None and route_current.path == "/":
|
|
492
463
|
with rv.Row(align="center"):
|
|
@@ -512,6 +483,7 @@ def Layout(children=[]):
|
|
|
512
483
|
overlay_opacity=0.5,
|
|
513
484
|
style_="height: 100vh",
|
|
514
485
|
):
|
|
486
|
+
Algolia()
|
|
515
487
|
with rv.List(nav=True):
|
|
516
488
|
with rv.ListItemGroup(active_class="text--primary"):
|
|
517
489
|
for route in all_routes:
|
|
@@ -520,32 +492,18 @@ def Layout(children=[]):
|
|
|
520
492
|
with solara.Link(route):
|
|
521
493
|
solara.ListItem(route.label)
|
|
522
494
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
current_path = router.path
|
|
536
|
-
with rv.ListItemGroup(active_class="text--primary", v_model=current_path):
|
|
537
|
-
for route in all_routes_sidebar:
|
|
538
|
-
# this gets rid of the api/link child routes
|
|
539
|
-
if len([k for k in route.children if k.label]) == 0:
|
|
540
|
-
with solara.Link(route):
|
|
541
|
-
solara.ListItem(route.label, value=solara.resolve_path(route))
|
|
542
|
-
else:
|
|
543
|
-
with solara.ListItem(route.label or "no-title", value=solara.resolve_path(route) + "_no_select"):
|
|
544
|
-
for subroute in route.children:
|
|
545
|
-
if subroute.label:
|
|
546
|
-
with solara.Link(subroute):
|
|
547
|
-
with solara.ListItem(subroute.label, value=solara.resolve_path(subroute)):
|
|
548
|
-
pass
|
|
495
|
+
if route_current is not None and route_current.module is not None and hasattr(route_current.module, "Sidebar"):
|
|
496
|
+
with solara.v.NavigationDrawer(
|
|
497
|
+
absolute=True,
|
|
498
|
+
clipped=True,
|
|
499
|
+
class_="d-md-none d-block",
|
|
500
|
+
height="unset",
|
|
501
|
+
style_="min-height: 100vh;",
|
|
502
|
+
v_model=show_left_menu,
|
|
503
|
+
on_v_model=set_show_left_menu,
|
|
504
|
+
width="20rem",
|
|
505
|
+
):
|
|
506
|
+
route_current.module.Sidebar()
|
|
549
507
|
|
|
550
508
|
return main
|
|
551
509
|
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Solara Changelog
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
## Version 1.31
|
|
5
|
+
|
|
6
|
+
We changed solara from a single package into multiple packages.
|
|
7
|
+
|
|
8
|
+
The `solara` package is a meta package that installs all the necessary dependencies to get started with Solara. By default, we install:
|
|
9
|
+
|
|
10
|
+
* [`pip install "solara-ui[all]"`](https://pypi.org/project/solara-ui)
|
|
11
|
+
* [`pip install "solara-server[starlette,dev]"`](https://pypi.org/project/solara-ui)
|
|
12
|
+
|
|
13
|
+
Notebook users can simply install `solara-ui` if they do not need the solara-server. Read our [installation guide](https://solara.dev/documentation/getting_started/installing) for more information.
|
|
14
|
+
|
|
3
15
|
## Version 1.30.1
|
|
4
16
|
|
|
5
17
|
### Details
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
import solara
|
|
4
|
+
from solara.website.components.sidebar import Sidebar
|
|
4
5
|
|
|
5
6
|
_title = "Documentation"
|
|
6
7
|
|
|
7
8
|
HERE = Path(__file__).parent
|
|
9
|
+
Sidebar = Sidebar
|
|
8
10
|
|
|
9
11
|
route_order = ["/", "getting_started", "examples", "components", "api", "advanced", "faq"]
|
|
10
12
|
|
|
@@ -79,94 +81,6 @@ def Page(children=[]):
|
|
|
79
81
|
pass
|
|
80
82
|
|
|
81
83
|
|
|
82
|
-
@solara.component
|
|
83
|
-
def Sidebar():
|
|
84
|
-
route_current, all_routes = solara.use_route()
|
|
85
|
-
router = solara.use_router()
|
|
86
|
-
if route_current is None:
|
|
87
|
-
return solara.Error("Page not found")
|
|
88
|
-
|
|
89
|
-
with solara.v.NavigationDrawer(
|
|
90
|
-
clipped=True, width="20rem", height="unset", style_="min-height: calc(100vh - 215.5px);", class_="d-none d-md-block"
|
|
91
|
-
) as main:
|
|
92
|
-
with solara.v.List(expand=True, nav=True, style_="height: calc(100vh - 215.5px); display: flex; flex-direction: column;"):
|
|
93
|
-
with solara.v.ListItemGroup(v_model=router.path):
|
|
94
|
-
for route in all_routes:
|
|
95
|
-
if len(route.children) == 1 or route.path == "/":
|
|
96
|
-
with solara.Link("/documentation/" + route.path if route.path != "/" else "/documentation"):
|
|
97
|
-
with solara.v.ListItem(value="/documentation/" + route.path if route.path != "/" else "/documentation"):
|
|
98
|
-
if route.path == "/":
|
|
99
|
-
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-home"])])
|
|
100
|
-
solara.v.ListItemTitle(style_="padding: 0 20px;", children=[route.label])
|
|
101
|
-
else:
|
|
102
|
-
with solara.v.ListGroup(
|
|
103
|
-
v_slots=[
|
|
104
|
-
{
|
|
105
|
-
"name": "activator",
|
|
106
|
-
"children": solara.v.ListItemTitle(
|
|
107
|
-
children=[route.label],
|
|
108
|
-
style_="padding: 0 20px;",
|
|
109
|
-
),
|
|
110
|
-
}
|
|
111
|
-
],
|
|
112
|
-
value=router.path.startswith("/documentation/" + route.path),
|
|
113
|
-
):
|
|
114
|
-
for item in route.children:
|
|
115
|
-
if item.path == "/":
|
|
116
|
-
continue
|
|
117
|
-
if item.children != [] and any([c.label is not None and c.path != "/" for c in item.children]):
|
|
118
|
-
with solara.v.ListGroup(
|
|
119
|
-
v_slots=[
|
|
120
|
-
{
|
|
121
|
-
"name": "activator",
|
|
122
|
-
"children": solara.v.ListItemTitle(
|
|
123
|
-
children=[item.label],
|
|
124
|
-
),
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
sub_group=True,
|
|
128
|
-
no_action=True,
|
|
129
|
-
value=router.path.startswith("/documentation/" + route.path + "/" + item.path),
|
|
130
|
-
):
|
|
131
|
-
for subitem in item.children:
|
|
132
|
-
# skip pages that are only used to demonstrate Link or Router usage
|
|
133
|
-
if subitem.path == "/" or subitem.label is None:
|
|
134
|
-
continue
|
|
135
|
-
path = (
|
|
136
|
-
"/documentation/" + route.path + "/" + item.path + "/" + subitem.path
|
|
137
|
-
if item.path != "fullscreen"
|
|
138
|
-
else "/apps/" + subitem.path
|
|
139
|
-
)
|
|
140
|
-
with solara.Link(
|
|
141
|
-
path,
|
|
142
|
-
):
|
|
143
|
-
with solara.v.ListItem(dense=True, style_="padding: 0 20px;", value=path):
|
|
144
|
-
solara.v.ListItemContent(
|
|
145
|
-
children=[subitem.label],
|
|
146
|
-
)
|
|
147
|
-
else:
|
|
148
|
-
with solara.v.ListItemGroup(value="/documentation/" + route.path + "/" + item.path):
|
|
149
|
-
with solara.Link(
|
|
150
|
-
"/documentation/" + route.path + "/" + item.path,
|
|
151
|
-
):
|
|
152
|
-
with solara.v.ListItem(dense=True, style_="padding: 0 20px;"):
|
|
153
|
-
solara.v.ListItemContent(
|
|
154
|
-
children=[item.label],
|
|
155
|
-
)
|
|
156
|
-
solara.v.Spacer(style_="flex-grow: 1;")
|
|
157
|
-
with solara.v.ListItemGroup():
|
|
158
|
-
with solara.Link("/contact"):
|
|
159
|
-
with solara.v.ListItem():
|
|
160
|
-
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-email"])])
|
|
161
|
-
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Contact"])
|
|
162
|
-
with solara.Link("/changelog"):
|
|
163
|
-
with solara.v.ListItem():
|
|
164
|
-
solara.v.ListItemIcon(children=[solara.v.Icon(children=["mdi-history"])])
|
|
165
|
-
solara.v.ListItemTitle(style_="padding: 0 20px;", children=["Changelog"])
|
|
166
|
-
|
|
167
|
-
return main
|
|
168
|
-
|
|
169
|
-
|
|
170
84
|
@solara.component
|
|
171
85
|
def Layout(children=[]):
|
|
172
86
|
route_current, all_routes = solara.use_route()
|