dara-components 1.8.5__py3-none-any.whl → 1.22.1__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.
- dara/components/__init__.py +18 -0
- dara/components/_assets/__init__.py +30 -0
- dara/components/_assets/auto_js/.gitkeep +0 -0
- dara/components/_assets/auto_js/dara.components.css +1494 -0
- dara/components/_assets/auto_js/dara.components.umd.js +182837 -0
- dara/components/_assets/common/bokeh-3.1.1.min.js +690 -0
- dara/components/_assets/common/bokeh-api-3.1.1.min.js +60 -0
- dara/components/_assets/common/bokeh-gl-3.1.1.min.js +67 -0
- dara/components/_assets/common/bokeh-mathjax-3.1.1.min.js +329 -0
- dara/components/_assets/common/bokeh-tables-3.1.1.min.js +132 -0
- dara/components/_assets/common/bokeh-widgets-3.1.1.min.js +129 -0
- dara/components/_assets/common/pixi-filters.min.js +17 -0
- dara/components/_assets/common/pixi.min.js +2214 -0
- dara/components/_assets/common/pixi_viewport.js +1 -0
- dara/components/_assets/common/plotly.min.js +8 -0
- dara/components/common/__init__.py +11 -2
- dara/components/common/accordion.py +20 -26
- dara/components/common/anchor.py +9 -10
- dara/components/common/base_component.py +23 -36
- dara/components/common/bullet_list.py +1 -3
- dara/components/common/button.py +35 -26
- dara/components/common/button_bar.py +25 -20
- dara/components/common/card.py +4 -5
- dara/components/common/carousel.py +9 -9
- dara/components/common/checkbox_group.py +26 -19
- dara/components/common/code.py +8 -5
- dara/components/common/component_select_list.py +9 -13
- dara/components/common/datepicker.py +16 -16
- dara/components/common/dropdown_menu.py +161 -0
- dara/components/common/dropzone.py +42 -33
- dara/components/common/form.py +5 -7
- dara/components/common/form_page.py +4 -6
- dara/components/common/grid.py +21 -18
- dara/components/common/heading.py +5 -4
- dara/components/common/icon.py +1 -3
- dara/components/common/if_cmp.py +23 -17
- dara/components/common/image.py +2 -2
- dara/components/common/input.py +9 -11
- dara/components/common/label.py +13 -14
- dara/components/common/markdown.py +3 -5
- dara/components/common/modal.py +2 -2
- dara/components/common/overlay.py +8 -14
- dara/components/common/paragraph.py +2 -2
- dara/components/common/progress_bar.py +6 -8
- dara/components/common/radio_group.py +38 -21
- dara/components/common/select.py +33 -30
- dara/components/common/slider.py +74 -29
- dara/components/common/spacer.py +4 -6
- dara/components/common/stack.py +7 -4
- dara/components/common/switch.py +6 -8
- dara/components/common/tabbed_card.py +8 -11
- dara/components/common/table.py +224 -73
- dara/components/common/text.py +7 -9
- dara/components/common/textarea.py +7 -7
- dara/components/common/time_utils.py +2 -5
- dara/components/common/tooltip.py +4 -6
- dara/components/common/utils.py +29 -35
- dara/components/graphs/__init__.py +1 -0
- dara/components/graphs/components/base_graph_component.py +34 -22
- dara/components/graphs/components/causal_graph_viewer.py +13 -15
- dara/components/graphs/components/edge_encoder.py +49 -26
- dara/components/graphs/components/node_hierarchy_builder.py +17 -16
- dara/components/graphs/definitions.py +27 -20
- dara/components/graphs/graph_layout.py +90 -53
- dara/components/plotting/__init__.py +2 -1
- dara/components/plotting/bokeh/bokeh.py +7 -10
- dara/components/plotting/bokeh/utils.py +5 -3
- dara/components/plotting/plotly/plotly.py +24 -19
- dara/components/plotting/plotly/themes.py +7 -5
- dara/components/smart/__init__.py +7 -1
- dara/components/smart/chat/chat.py +7 -8
- dara/components/smart/chat/config.py +1 -1
- dara/components/smart/chat/types.py +4 -6
- dara/components/smart/code_editor/code_editor.py +18 -4
- dara/components/smart/code_editor/util.py +11 -11
- dara/components/smart/data_slicer/__init__.py +4 -0
- dara/components/smart/data_slicer/data_slicer.py +14 -18
- dara/components/smart/data_slicer/data_slicer_modal.py +4 -6
- dara/components/smart/data_slicer/extension/data_slicer_filter.py +3 -4
- dara/components/smart/data_slicer/extension/filter_status_button.py +1 -3
- dara/components/smart/data_slicer/utils/core.py +23 -23
- dara/components/smart/data_slicer/utils/data_preview.py +1 -3
- dara/components/smart/data_slicer/utils/plotting.py +8 -6
- dara/components/smart/hierarchy.py +9 -10
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/METADATA +7 -7
- dara_components-1.22.1.dist-info/RECORD +100 -0
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/WHEEL +1 -1
- dara_components-1.22.1.dist-info/entry_points.txt +3 -0
- dara/components/umd/dara.components.umd.js +0 -396288
- dara/components/umd/style.css +0 -745
- dara_components-1.8.5.dist-info/RECORD +0 -86
- {dara_components-1.8.5.dist-info → dara_components-1.22.1.dist-info}/LICENSE +0 -0
|
@@ -17,9 +17,10 @@ limitations under the License.
|
|
|
17
17
|
|
|
18
18
|
import abc
|
|
19
19
|
from enum import Enum
|
|
20
|
-
from typing import List, Optional, Union
|
|
21
20
|
|
|
22
|
-
from pydantic import
|
|
21
|
+
from pydantic import Field
|
|
22
|
+
|
|
23
|
+
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class GraphLayoutType(Enum):
|
|
@@ -47,7 +48,7 @@ class LayeringAlgorithm(Enum):
|
|
|
47
48
|
SIMPLEX = 'simplex'
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
Number =
|
|
51
|
+
Number = int | float
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
class GraphLayout(BaseModel, abc.ABC):
|
|
@@ -58,25 +59,25 @@ class GraphLayout(BaseModel, abc.ABC):
|
|
|
58
59
|
:param node_font_size: node font size in pixels
|
|
59
60
|
"""
|
|
60
61
|
|
|
61
|
-
node_size:
|
|
62
|
-
node_font_size:
|
|
62
|
+
node_size: int | None = None
|
|
63
|
+
node_font_size: int | None = None
|
|
63
64
|
|
|
64
65
|
|
|
65
66
|
class TiersConfig(BaseModel):
|
|
66
|
-
"""
|
|
67
|
+
r"""
|
|
67
68
|
TiersConfig provides a way of defining tiers for a graph layout.
|
|
68
69
|
|
|
69
70
|
:param group: Path within node to group property which defines the tier it belong to,
|
|
70
|
-
e.g. 'meta.group' would correspond to a group attribute in the meta of the node, 'meta': {'group': 'countries'}
|
|
71
|
+
e.g. 'meta.group' would correspond to a group attribute in the meta of the node, 'meta': \{'group': 'countries'\}
|
|
71
72
|
:param order_nodes_by: A path to a node property which contains a number defining the order of nodes within a tier,
|
|
72
|
-
e.g. 'meta.order' would correspond to an order attribute in the meta of the node, 'meta': {'order': 1}
|
|
73
|
+
e.g. 'meta.order' would correspond to an order attribute in the meta of the node, 'meta': \{'order': 1\}
|
|
73
74
|
:param rank: A list of group values defining the order they should appear in, e.g. ['countries', 'currency', 'industry']
|
|
74
75
|
would result in the nodes representing nodes appearing in the first tier, then nodes representing currency in the second tier and finally those representing industry.
|
|
75
76
|
"""
|
|
76
77
|
|
|
77
78
|
group: str
|
|
78
|
-
order_nodes_by:
|
|
79
|
-
rank:
|
|
79
|
+
order_nodes_by: str | None = None
|
|
80
|
+
rank: list[str] | None = None
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
class TieringLayout(BaseModel):
|
|
@@ -133,8 +134,42 @@ class TieringLayout(BaseModel):
|
|
|
133
134
|
:param orientation: Orientation the tiers are displayed in default is horizontal
|
|
134
135
|
"""
|
|
135
136
|
|
|
136
|
-
tiers:
|
|
137
|
-
orientation:
|
|
137
|
+
tiers: TiersConfig | list[list[str]] | None = None
|
|
138
|
+
orientation: DirectionType | None = DirectionType.HORIZONTAL
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class GroupingLayout(BaseModel):
|
|
142
|
+
"""
|
|
143
|
+
GroupingLayout provides a grouping or cluster layout for a graph. It can be used to represent nodes within groups or cluster which are collapsible.
|
|
144
|
+
|
|
145
|
+
You can set the group on the meta of a node and then define the path to this property on the layout:
|
|
146
|
+
```
|
|
147
|
+
from dara.components import CausalGraphViewer, FcoseLayout
|
|
148
|
+
from cai_causal_graph import CausalGraph
|
|
149
|
+
|
|
150
|
+
cg = CausalGraph()
|
|
151
|
+
cg.add_node(identifier='A', meta={'group': 'group1'})
|
|
152
|
+
cg.add_node(identifier='B', meta={'group': 'group1'})
|
|
153
|
+
cg.add_node(identifier='C', meta={'group': 'group2'})
|
|
154
|
+
cg.add_node(identifier='D', meta={'group': 'group2'})
|
|
155
|
+
cg.add_node(identifier='E', meta={'group': 'group3'})
|
|
156
|
+
cg.add_edge('A', 'C')
|
|
157
|
+
cg.add_edge('B', 'D')
|
|
158
|
+
cg.add_edge('C', 'E')
|
|
159
|
+
cg.add_edge('D', 'E')
|
|
160
|
+
|
|
161
|
+
CausalGraphViewer(
|
|
162
|
+
causal_graph=cg,
|
|
163
|
+
graph_layout=FcoseLayout(
|
|
164
|
+
group='meta.group',
|
|
165
|
+
),
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
:param group: Path within node to group property which defines the group it belong to,
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
group: str | None = None
|
|
138
173
|
|
|
139
174
|
|
|
140
175
|
class CircularLayout(GraphLayout):
|
|
@@ -145,7 +180,7 @@ class CircularLayout(GraphLayout):
|
|
|
145
180
|
:param node_size: node size in pixels
|
|
146
181
|
"""
|
|
147
182
|
|
|
148
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.CIRCULAR,
|
|
183
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.CIRCULAR, frozen=True)
|
|
149
184
|
|
|
150
185
|
|
|
151
186
|
class CustomLayout(GraphLayout):
|
|
@@ -172,12 +207,12 @@ class CustomLayout(GraphLayout):
|
|
|
172
207
|
If not all nodes have coordinates defined, the graph editor will fall back to a default layout.
|
|
173
208
|
"""
|
|
174
209
|
|
|
175
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.CUSTOM,
|
|
210
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.CUSTOM, frozen=True)
|
|
176
211
|
|
|
177
212
|
|
|
178
|
-
class FcoseLayout(GraphLayout, TieringLayout):
|
|
213
|
+
class FcoseLayout(GraphLayout, TieringLayout, GroupingLayout):
|
|
179
214
|
"""
|
|
180
|
-
FcoseLayout
|
|
215
|
+
FcoseLayout utilizes `fCoSE` (fast Compound Spring Embedder) algorithm to compute the layout.
|
|
181
216
|
It works well in most circumstances and is highly configurable.
|
|
182
217
|
|
|
183
218
|
See https://github.com/iVis-at-Bilkent/cytoscape.js-fcose for more details and interactive demos.
|
|
@@ -194,23 +229,23 @@ class FcoseLayout(GraphLayout, TieringLayout):
|
|
|
194
229
|
:param tier_separation: Separation force between tiers (default value: 200)
|
|
195
230
|
"""
|
|
196
231
|
|
|
197
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.FCOSE,
|
|
232
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.FCOSE, frozen=True)
|
|
198
233
|
|
|
199
|
-
edge_elasticity:
|
|
200
|
-
edge_length:
|
|
201
|
-
energy:
|
|
202
|
-
gravity:
|
|
203
|
-
gravity_range:
|
|
204
|
-
high_quality:
|
|
205
|
-
iterations:
|
|
206
|
-
node_repulsion:
|
|
207
|
-
node_separation:
|
|
208
|
-
tier_separation:
|
|
234
|
+
edge_elasticity: Number | None = 0.45
|
|
235
|
+
edge_length: Number | None = 3
|
|
236
|
+
energy: Number | None = 0.1
|
|
237
|
+
gravity: Number | None = 35
|
|
238
|
+
gravity_range: Number | None = 80
|
|
239
|
+
high_quality: bool | None = True
|
|
240
|
+
iterations: int | None = 2500
|
|
241
|
+
node_repulsion: Number | None = 6_500
|
|
242
|
+
node_separation: Number | None = 75
|
|
243
|
+
tier_separation: Number | None = 200
|
|
209
244
|
|
|
210
245
|
|
|
211
246
|
class ForceAtlasLayout(GraphLayout):
|
|
212
247
|
"""
|
|
213
|
-
ForceAtlas
|
|
248
|
+
ForceAtlas utilizes the `ForceAtlas2` algorithm to compute the layout. It is a force-directed layout
|
|
214
249
|
which integrates various optimizations and is highly configurable.
|
|
215
250
|
|
|
216
251
|
See https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679 for more details and
|
|
@@ -224,7 +259,7 @@ class ForceAtlasLayout(GraphLayout):
|
|
|
224
259
|
of the space. Its main purpose is to compensate repulsion for nodes that are far away from the center. (default value:0.2)
|
|
225
260
|
:param iterations: Number of iterations to run the layout for, per computation (default value: 10_000)
|
|
226
261
|
:param lin_log_mode: Whether to use LinLog energy model, using logarithmic attraction force. Enabling it makes clusters
|
|
227
|
-
tighter but
|
|
262
|
+
tighter but converges slower. (default value: `True`)
|
|
228
263
|
:param outbound_attraction_distribution: Whether to scale the attraction force between nodes according to their degree. (default value: `True`)
|
|
229
264
|
:param scaling_ratio: Parameter to adjust the size of the produced graph (default value: 8)
|
|
230
265
|
:param strong_gravity_mode: Whether to use strong gravity mode, which sets a force that attracts the nodes that are distant
|
|
@@ -232,16 +267,16 @@ class ForceAtlasLayout(GraphLayout):
|
|
|
232
267
|
However, its advantage is to force a very compact layout, which may be useful for certain purposes. (default value: `False`)
|
|
233
268
|
"""
|
|
234
269
|
|
|
235
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.FORCE_ATLAS,
|
|
270
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.FORCE_ATLAS, frozen=True)
|
|
236
271
|
|
|
237
|
-
barnes_hut_optimize:
|
|
238
|
-
edge_weight_influence:
|
|
239
|
-
gravity:
|
|
240
|
-
iterations:
|
|
241
|
-
lin_log_mode:
|
|
242
|
-
outbound_attraction_distribution:
|
|
243
|
-
scaling_ratio:
|
|
244
|
-
strong_gravity_mode:
|
|
272
|
+
barnes_hut_optimize: bool | None = False
|
|
273
|
+
edge_weight_influence: Number | None = 1
|
|
274
|
+
gravity: Number | None = 0.2
|
|
275
|
+
iterations: int | None = 10_000
|
|
276
|
+
lin_log_mode: bool | None = True
|
|
277
|
+
outbound_attraction_distribution: bool | None = True
|
|
278
|
+
scaling_ratio: Number | None = 8
|
|
279
|
+
strong_gravity_mode: bool | None = False
|
|
245
280
|
|
|
246
281
|
|
|
247
282
|
class MarketingLayout(GraphLayout, TieringLayout):
|
|
@@ -254,9 +289,9 @@ class MarketingLayout(GraphLayout, TieringLayout):
|
|
|
254
289
|
:param tier_separation: Separation force between tiers (default value: 300)
|
|
255
290
|
"""
|
|
256
291
|
|
|
257
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.MARKETING,
|
|
258
|
-
target_location:
|
|
259
|
-
tier_separation:
|
|
292
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.MARKETING, frozen=True)
|
|
293
|
+
target_location: TargetLocation | None = None
|
|
294
|
+
tier_separation: Number | None = 300
|
|
260
295
|
|
|
261
296
|
|
|
262
297
|
class PlanarLayout(GraphLayout, TieringLayout):
|
|
@@ -265,20 +300,20 @@ class PlanarLayout(GraphLayout, TieringLayout):
|
|
|
265
300
|
uses d3-dag's sugiyama layout under the hood to minimize edge crossings.
|
|
266
301
|
|
|
267
302
|
:param orientation: Orientation of target node relative to other nodes (horizontal or vertical). (default value: horizontal)
|
|
268
|
-
:param layering_algorithm: Algorithm to use for the layering step of sugyiama algorithm. Can
|
|
303
|
+
:param layering_algorithm: Algorithm to use for the layering step of sugyiama algorithm. Can chosen between simplex which
|
|
269
304
|
optimizes for minimum edge length or long path which optimizes for minimum graph height.
|
|
270
305
|
Do note that if tiers are passed in conjunction to this prop, its value will revert to simplex
|
|
271
306
|
as tiers are only supported by it (defaults to: simplex)
|
|
272
307
|
"""
|
|
273
308
|
|
|
274
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.PLANAR,
|
|
275
|
-
layering_algorithm:
|
|
276
|
-
orientation:
|
|
309
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.PLANAR, frozen=True)
|
|
310
|
+
layering_algorithm: LayeringAlgorithm | None = LayeringAlgorithm.SIMPLEX
|
|
311
|
+
orientation: DirectionType | None = None
|
|
277
312
|
|
|
278
313
|
|
|
279
|
-
class SpringLayout(GraphLayout, TieringLayout):
|
|
314
|
+
class SpringLayout(GraphLayout, TieringLayout, GroupingLayout):
|
|
280
315
|
"""
|
|
281
|
-
SpringLayout provides a simple force-directed graph layout which produces the "spring"
|
|
316
|
+
SpringLayout provides a simple force-directed graph layout which produces the "spring" behavior of edges.
|
|
282
317
|
This is a 'live' layout, which means a simulation keeps running in the background to compute the layout.
|
|
283
318
|
|
|
284
319
|
:param collision_force: Multiplier for collision force between nodes (default value: 2)
|
|
@@ -288,12 +323,14 @@ class SpringLayout(GraphLayout, TieringLayout):
|
|
|
288
323
|
make the initial render of the graph more stable (i.e. nodes won't move by themselves) but it comes at a
|
|
289
324
|
small performance cost. (default value: 100)
|
|
290
325
|
:param tier_separation: Separation force between tiers (default value: 300)
|
|
326
|
+
:param group_repel_strength: Strength of repulsion force between groups (default value: 2000)
|
|
291
327
|
"""
|
|
292
328
|
|
|
293
|
-
layout_type: GraphLayoutType = Field(default=GraphLayoutType.SPRING,
|
|
329
|
+
layout_type: GraphLayoutType = Field(default=GraphLayoutType.SPRING, frozen=True)
|
|
294
330
|
|
|
295
|
-
collision_force:
|
|
296
|
-
gravity:
|
|
297
|
-
link_force:
|
|
298
|
-
warmup_ticks:
|
|
299
|
-
tier_separation:
|
|
331
|
+
collision_force: Number | None = 2
|
|
332
|
+
gravity: Number | None = -50
|
|
333
|
+
link_force: Number | None = 5
|
|
334
|
+
warmup_ticks: Number | None = 100
|
|
335
|
+
tier_separation: Number | None = 300
|
|
336
|
+
group_repel_strength: Number | None = 2000
|
|
@@ -14,8 +14,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
+
# ruff: noqa: F401, F403
|
|
17
18
|
|
|
18
|
-
import dara.components.plotting.palettes as PALETTES
|
|
19
|
+
import dara.components.plotting.palettes as PALETTES
|
|
19
20
|
from dara.components.plotting.bokeh import *
|
|
20
21
|
from dara.components.plotting.matplotlib import *
|
|
21
22
|
from dara.components.plotting.plotly import *
|
|
@@ -16,10 +16,11 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from json import dumps
|
|
19
|
-
from typing import Any
|
|
19
|
+
from typing import Any
|
|
20
20
|
|
|
21
21
|
from bokeh.document import Document
|
|
22
22
|
from bokeh.themes import Theme
|
|
23
|
+
from pydantic import ConfigDict
|
|
23
24
|
|
|
24
25
|
from dara.components.plotting.bokeh.themes import light_theme
|
|
25
26
|
from dara.core.base_definitions import Action
|
|
@@ -28,7 +29,7 @@ from dara.core.definitions import StyledComponentInstance
|
|
|
28
29
|
SETTINGS = {'THEME': light_theme}
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
def _get_theme(theme_input:
|
|
32
|
+
def _get_theme(theme_input: dict | None):
|
|
32
33
|
if theme_input is not None:
|
|
33
34
|
return Theme(json=theme_input)
|
|
34
35
|
else:
|
|
@@ -51,19 +52,16 @@ class Bokeh(StyledComponentInstance):
|
|
|
51
52
|
js_module = '@darajs/components'
|
|
52
53
|
|
|
53
54
|
document: str
|
|
54
|
-
events:
|
|
55
|
+
events: list[tuple[str, Action]] | None = None
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
arbitrary_types_allowed = True
|
|
58
|
-
json_encoders = {Document: lambda v: v.to_json()}
|
|
59
|
-
use_enum_values = True
|
|
57
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, use_enum_values=True)
|
|
60
58
|
|
|
61
59
|
def __init__(
|
|
62
60
|
self,
|
|
63
61
|
figure: Any = None,
|
|
64
62
|
document: Any = None,
|
|
65
|
-
theme:
|
|
66
|
-
events:
|
|
63
|
+
theme: dict | None = None,
|
|
64
|
+
events: list[tuple[str, Action]] | None = None,
|
|
67
65
|
**kwargs,
|
|
68
66
|
):
|
|
69
67
|
"""
|
|
@@ -71,7 +69,6 @@ class Bokeh(StyledComponentInstance):
|
|
|
71
69
|
:param document: the document to display
|
|
72
70
|
"""
|
|
73
71
|
if figure is not None:
|
|
74
|
-
|
|
75
72
|
doc = Document()
|
|
76
73
|
doc.theme = _get_theme(theme)
|
|
77
74
|
doc.add_root(figure)
|
|
@@ -35,21 +35,23 @@ def figure_events(fig: figure):
|
|
|
35
35
|
:param
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
-
def generate_event(args: dict =
|
|
38
|
+
def generate_event(args: dict | None = None):
|
|
39
39
|
"""
|
|
40
40
|
Generate a CustomJS event with the code, event name and arguments provided
|
|
41
41
|
|
|
42
42
|
:param args: The arguments to provide to the JS code
|
|
43
43
|
"""
|
|
44
|
+
if args is None:
|
|
45
|
+
args = {}
|
|
44
46
|
return CustomJS(
|
|
45
47
|
args=args,
|
|
46
48
|
code=f"""
|
|
47
|
-
function {event_name.replace(' ','')+'__'+fig.id}(cb_obj, args) {{
|
|
49
|
+
function {event_name.replace(' ', '') + '__' + fig.id}(cb_obj, args) {{
|
|
48
50
|
{code}
|
|
49
51
|
}}
|
|
50
52
|
|
|
51
53
|
document.dispatchEvent(
|
|
52
|
-
new CustomEvent("BOKEH_FIGURE_{event_name}_{fig.id}", {{ detail: {event_name.replace(' ','')+'__'+fig.id}(cb_obj, {{{','.join(args.keys())}}}) }})
|
|
54
|
+
new CustomEvent("BOKEH_FIGURE_{event_name}_{fig.id}", {{ detail: {event_name.replace(' ', '') + '__' + fig.id}(cb_obj, {{{','.join(args.keys())}}}) }})
|
|
53
55
|
)
|
|
54
56
|
""",
|
|
55
57
|
)
|
|
@@ -16,17 +16,27 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from enum import Enum
|
|
19
|
-
from typing import Any,
|
|
19
|
+
from typing import Any, ClassVar
|
|
20
20
|
|
|
21
21
|
import plotly.graph_objects as go
|
|
22
|
-
|
|
22
|
+
import plotly.io as pio
|
|
23
|
+
from pydantic import ConfigDict
|
|
23
24
|
|
|
24
25
|
from dara.components.plotting.plotly.themes import light_theme
|
|
25
26
|
from dara.core.base_definitions import Action
|
|
27
|
+
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
26
28
|
from dara.core.definitions import StyledComponentInstance
|
|
27
29
|
|
|
28
30
|
SETTINGS = {'THEME': light_theme}
|
|
29
31
|
|
|
32
|
+
# We need to set the default theme for plotly so that plotly express when setting traces is able to pick up dara theme colors
|
|
33
|
+
base_template = pio.templates['plotly']
|
|
34
|
+
dara_theme = base_template.layout.update(SETTINGS['THEME']['layout']) # type: ignore
|
|
35
|
+
dara_template = go.layout.Template(layout=dara_theme)
|
|
36
|
+
# Set the default theme for plotly
|
|
37
|
+
pio.templates['dara_theme'] = dara_template
|
|
38
|
+
pio.templates.default = 'dara_theme'
|
|
39
|
+
|
|
30
40
|
|
|
31
41
|
class PlotlyEventName(str, Enum):
|
|
32
42
|
"""
|
|
@@ -70,8 +80,8 @@ class PlotlyEvent(BaseModel):
|
|
|
70
80
|
"""
|
|
71
81
|
|
|
72
82
|
event_name: PlotlyEventName
|
|
73
|
-
actions:
|
|
74
|
-
custom_js:
|
|
83
|
+
actions: list[Action] | None = None
|
|
84
|
+
custom_js: str | None = None
|
|
75
85
|
|
|
76
86
|
|
|
77
87
|
class Plotly(StyledComponentInstance):
|
|
@@ -91,12 +101,8 @@ class Plotly(StyledComponentInstance):
|
|
|
91
101
|
fig = px.scatter(df, x='sepal_width', y='sepal_length', color='species', title='Iris Dataset Scatter Plot')
|
|
92
102
|
|
|
93
103
|
|
|
94
|
-
def plotly_page():
|
|
95
|
-
return Plotly(figure=fig, min_height=100)
|
|
96
|
-
|
|
97
|
-
|
|
98
104
|
config = ConfigurationBuilder()
|
|
99
|
-
config.add_page(
|
|
105
|
+
config.router.add_page(path='my-plot', content=Plotly(figure=fig, min_height=100))
|
|
100
106
|
```
|
|
101
107
|
|
|
102
108
|
:param figure: A plotly figure
|
|
@@ -106,24 +112,23 @@ class Plotly(StyledComponentInstance):
|
|
|
106
112
|
js_module = '@darajs/components'
|
|
107
113
|
|
|
108
114
|
figure: str
|
|
109
|
-
events:
|
|
115
|
+
events: list[PlotlyEvent] | None = None
|
|
110
116
|
|
|
111
|
-
EventName = PlotlyEventName
|
|
112
|
-
Event = PlotlyEvent
|
|
117
|
+
EventName: ClassVar[type[PlotlyEventName]] = PlotlyEventName
|
|
118
|
+
Event: ClassVar[type[PlotlyEvent]] = PlotlyEvent
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
arbitrary_types_allowed
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
model_config = ConfigDict(
|
|
121
|
+
arbitrary_types_allowed=True,
|
|
122
|
+
use_enum_values=True,
|
|
123
|
+
)
|
|
118
124
|
|
|
119
125
|
def __init__(
|
|
120
126
|
self,
|
|
121
127
|
figure: Any = None,
|
|
122
|
-
theme:
|
|
123
|
-
events:
|
|
128
|
+
theme: dict | None = None,
|
|
129
|
+
events: list[PlotlyEvent] | None = None,
|
|
124
130
|
**kwargs,
|
|
125
131
|
):
|
|
126
|
-
|
|
127
132
|
if theme is None and figure is not None:
|
|
128
133
|
figure.update_layout(template=theme if theme is not None else SETTINGS['THEME'])
|
|
129
134
|
|
|
@@ -15,15 +15,17 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import Any
|
|
18
|
+
from typing import Any
|
|
19
19
|
|
|
20
20
|
from dara.components.plotting.palettes import CategoricalDark10, CategoricalLight10
|
|
21
21
|
from dara.core.visual.themes import dark, light
|
|
22
22
|
|
|
23
23
|
light_colors = light.Light.colors
|
|
24
|
+
assert light_colors is not None
|
|
24
25
|
dark_colors = dark.Dark.colors
|
|
26
|
+
assert dark_colors is not None
|
|
25
27
|
|
|
26
|
-
light_theme = {
|
|
28
|
+
light_theme: dict[str, dict[str, Any]] = {
|
|
27
29
|
'layout': {
|
|
28
30
|
'paper_bgcolor': 'rgba(255,255,255,0)', # Set the background color of the plot
|
|
29
31
|
'plot_bgcolor': 'rgba(255,255,255,0)', # Set the background color of the plot area
|
|
@@ -81,9 +83,9 @@ light_theme = {
|
|
|
81
83
|
},
|
|
82
84
|
},
|
|
83
85
|
},
|
|
84
|
-
}
|
|
86
|
+
}
|
|
85
87
|
|
|
86
|
-
dark_theme = {
|
|
88
|
+
dark_theme: dict[str, dict[str, Any]] = {
|
|
87
89
|
'layout': {
|
|
88
90
|
'paper_bgcolor': 'rgba(255,255,255,0)', # Set the background color of the plot
|
|
89
91
|
'plot_bgcolor': 'rgba(255,255,255,0)', # Set the background color of the plot area
|
|
@@ -141,4 +143,4 @@ dark_theme = {
|
|
|
141
143
|
},
|
|
142
144
|
},
|
|
143
145
|
},
|
|
144
|
-
}
|
|
146
|
+
}
|
|
@@ -14,16 +14,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
+
# ruff: noqa: F401, F403
|
|
17
18
|
|
|
18
19
|
from dara.components.smart.chat import Chat
|
|
19
20
|
from dara.components.smart.code_editor import CodeEditor, run_script
|
|
20
|
-
from dara.components.smart.data_slicer import
|
|
21
|
+
from dara.components.smart.data_slicer import (
|
|
22
|
+
DataSlicer,
|
|
23
|
+
DataSlicerModal,
|
|
24
|
+
FilterStatusButton,
|
|
25
|
+
)
|
|
21
26
|
from dara.components.smart.hierarchy import HierarchySelector, HierarchyViewer
|
|
22
27
|
from dara.components.smart.hierarchy import Node as HierarchyNode
|
|
23
28
|
|
|
24
29
|
__all__ = [
|
|
25
30
|
'DataSlicer',
|
|
26
31
|
'DataSlicerModal',
|
|
32
|
+
'FilterStatusButton',
|
|
27
33
|
'HierarchySelector',
|
|
28
34
|
'HierarchyViewer',
|
|
29
35
|
'HierarchyNode',
|
|
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from pydantic import
|
|
18
|
+
from pydantic import field_validator
|
|
19
19
|
|
|
20
20
|
from dara.components.smart.chat.endpoints import on_new_message
|
|
21
21
|
from dara.core.definitions import StyledComponentInstance
|
|
@@ -25,6 +25,8 @@ from dara.core.persistence import BackendStore
|
|
|
25
25
|
|
|
26
26
|
class Chat(StyledComponentInstance):
|
|
27
27
|
"""
|
|
28
|
+

|
|
29
|
+
|
|
28
30
|
A Chat component which can be added anywhere in your page. When added a chat button will appear in the bottom right
|
|
29
31
|
of your page and when clicked a chat sidebar will appear. This can be added on a page by page basis, with the chat
|
|
30
32
|
state being store in a Variable.
|
|
@@ -48,8 +50,8 @@ class Chat(StyledComponentInstance):
|
|
|
48
50
|
config.add_auth(MultiBasicAuthConfig(users={'user': 'password', 'user2': 'password2'}))
|
|
49
51
|
|
|
50
52
|
# Add a page with a chat component, this can be added anywhere within a page
|
|
51
|
-
config.add_page(
|
|
52
|
-
|
|
53
|
+
config.router.add_page(
|
|
54
|
+
path='chat',
|
|
53
55
|
content=Stack(
|
|
54
56
|
Text('This is a page with a chat'),
|
|
55
57
|
Chat(value=collab_variable),
|
|
@@ -65,12 +67,9 @@ class Chat(StyledComponentInstance):
|
|
|
65
67
|
|
|
66
68
|
value: NonDataVariable
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
extra = 'forbid'
|
|
70
|
-
|
|
71
|
-
@validator('value')
|
|
70
|
+
@field_validator('value')
|
|
72
71
|
@classmethod
|
|
73
|
-
def
|
|
72
|
+
def validate_variable(cls, value):
|
|
74
73
|
"""
|
|
75
74
|
Validate that the Variable has a store attached to it.
|
|
76
75
|
"""
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Copyright (c) 2023 by Impulse Innovations Ltd. Private and confidential. Part of the causaLens product.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import Callable
|
|
6
6
|
|
|
7
7
|
from dara.components.smart.chat.types import NewMessageBody
|
|
8
8
|
from dara.core.definitions import EndpointConfiguration
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
Copyright (c) 2023 by Impulse Innovations Ltd. Private and confidential. Part of the causaLens product.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
from pydantic import BaseModel
|
|
5
|
+
from dara.core.base_definitions import DaraBaseModel as BaseModel
|
|
8
6
|
|
|
9
7
|
|
|
10
8
|
class ChatUserData(BaseModel):
|
|
@@ -17,9 +15,9 @@ class ChatUserData(BaseModel):
|
|
|
17
15
|
:param groups: list of groups user belongs to
|
|
18
16
|
"""
|
|
19
17
|
|
|
20
|
-
id:
|
|
18
|
+
id: str | None = None
|
|
21
19
|
name: str
|
|
22
|
-
email:
|
|
20
|
+
email: str | None = None
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
class ChatMessage(BaseModel):
|
|
@@ -50,5 +48,5 @@ class NewMessageBody(BaseModel):
|
|
|
50
48
|
"""
|
|
51
49
|
|
|
52
50
|
app_url: str
|
|
53
|
-
users:
|
|
51
|
+
users: list[ChatUserData]
|
|
54
52
|
content: ChatMessage
|
|
@@ -15,20 +15,34 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
from typing import Literal
|
|
19
|
+
|
|
18
20
|
from dara.core.definitions import StyledComponentInstance
|
|
19
|
-
from dara.core.interactivity import
|
|
21
|
+
from dara.core.interactivity import ClientVariable
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
class CodeEditor(StyledComponentInstance):
|
|
23
25
|
"""
|
|
24
26
|
A code editor component.
|
|
25
27
|
|
|
28
|
+
Example usage:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from dara.components.smart.code_editor import CodeEditor
|
|
32
|
+
|
|
33
|
+
script = Variable('print("Hello, World!")')
|
|
34
|
+
|
|
35
|
+
code_editor = CodeEditor(
|
|
36
|
+
script=script,
|
|
37
|
+
language='python'
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
26
41
|
:param script: The script to render
|
|
27
42
|
"""
|
|
28
43
|
|
|
29
44
|
js_module = '@darajs/components'
|
|
30
45
|
|
|
31
|
-
script:
|
|
46
|
+
script: ClientVariable
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
extra = 'forbid'
|
|
48
|
+
language: Literal['json'] | Literal['python'] | Literal['markdown'] | Literal['sql'] | None = None
|