nova-trame 0.23.0__py3-none-any.whl → 0.23.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.
- nova/trame/model/data_selector.py +4 -0
- nova/trame/view/components/data_selector.py +27 -2
- nova/trame/view/components/ornl/neutron_data_selector.py +5 -1
- nova/trame/view_model/data_selector.py +12 -4
- nova/trame/view_model/ornl/neutron_data_selector.py +3 -3
- {nova_trame-0.23.0.dist-info → nova_trame-0.23.1.dist-info}/METADATA +1 -1
- {nova_trame-0.23.0.dist-info → nova_trame-0.23.1.dist-info}/RECORD +10 -10
- {nova_trame-0.23.0.dist-info → nova_trame-0.23.1.dist-info}/LICENSE +0 -0
- {nova_trame-0.23.0.dist-info → nova_trame-0.23.1.dist-info}/WHEEL +0 -0
- {nova_trame-0.23.0.dist-info → nova_trame-0.23.1.dist-info}/entry_points.txt +0 -0
@@ -47,6 +47,10 @@ class DataSelectorModel:
|
|
47
47
|
|
48
48
|
if len(path_parts) > 1:
|
49
49
|
dirs.clear()
|
50
|
+
elif path_parts != ["."]:
|
51
|
+
# Subdirectories are fully queried upon being opened, so we only need to query one item to determine
|
52
|
+
# if the target directory has any children.
|
53
|
+
dirs[:] = dirs[:1]
|
50
54
|
|
51
55
|
# Only create a new entry for top-level directories
|
52
56
|
if len(path_parts) == 1 and path_parts[0] != ".": # This indicates a top-level directory
|
@@ -1,5 +1,6 @@
|
|
1
1
|
"""View Implementation for DataSelector."""
|
2
2
|
|
3
|
+
from asyncio import ensure_future, sleep
|
3
4
|
from typing import Any, List, Optional, cast
|
4
5
|
|
5
6
|
from trame.app import get_server
|
@@ -8,7 +9,7 @@ from trame.widgets import vuetify3 as vuetify
|
|
8
9
|
|
9
10
|
from nova.mvvm.trame_binding import TrameBinding
|
10
11
|
from nova.trame.model.data_selector import DataSelectorModel, DataSelectorState
|
11
|
-
from nova.trame.view.layouts import GridLayout, VBoxLayout
|
12
|
+
from nova.trame.view.layouts import GridLayout, HBoxLayout, VBoxLayout
|
12
13
|
from nova.trame.view_model.data_selector import DataSelectorViewModel
|
13
14
|
|
14
15
|
from .input_field import InputField
|
@@ -25,6 +26,7 @@ class DataSelector(datagrid.VGrid):
|
|
25
26
|
directory: str,
|
26
27
|
extensions: Optional[List[str]] = None,
|
27
28
|
prefix: str = "",
|
29
|
+
refresh_rate: int = 30,
|
28
30
|
select_strategy: str = "all",
|
29
31
|
**kwargs: Any,
|
30
32
|
) -> None:
|
@@ -43,6 +45,9 @@ class DataSelector(datagrid.VGrid):
|
|
43
45
|
prefix : str, optional
|
44
46
|
A subdirectory within the selected top-level folder to show files. If not specified, the user will be shown
|
45
47
|
a folder browser and will be able to see all files in the selected top-level folder.
|
48
|
+
refresh_rate : int, optional
|
49
|
+
The number of seconds between attempts to automatically refresh the file list. Set to zero to disable this
|
50
|
+
feature. Defaults to 30 seconds.
|
46
51
|
select_strategy : str, optional
|
47
52
|
The selection strategy to pass to the `VDataTable component <https://trame.readthedocs.io/en/latest/trame.widgets.vuetify3.html#trame.widgets.vuetify3.VDataTable>`__.
|
48
53
|
If unset, the `all` strategy will be used.
|
@@ -73,6 +78,7 @@ class DataSelector(datagrid.VGrid):
|
|
73
78
|
self._directory = directory
|
74
79
|
self._extensions = extensions if extensions is not None else []
|
75
80
|
self._prefix = prefix
|
81
|
+
self._refresh_rate = refresh_rate
|
76
82
|
self._select_strategy = select_strategy
|
77
83
|
|
78
84
|
self._revogrid_id = f"nova__dataselector_{self._next_id}_rv"
|
@@ -91,9 +97,17 @@ class DataSelector(datagrid.VGrid):
|
|
91
97
|
|
92
98
|
self.create_ui(**kwargs)
|
93
99
|
|
100
|
+
ensure_future(self._refresh_loop())
|
101
|
+
|
94
102
|
def create_ui(self, *args: Any, **kwargs: Any) -> None:
|
95
103
|
with VBoxLayout(classes="nova-data-selector", height="100%") as self._layout:
|
96
|
-
|
104
|
+
with HBoxLayout(valign="center"):
|
105
|
+
self._layout.filter = html.Div(classes="flex-1-1")
|
106
|
+
with vuetify.VBtn(
|
107
|
+
classes="mx-1", density="compact", icon=True, variant="text", click=self.refresh_contents
|
108
|
+
):
|
109
|
+
vuetify.VIcon("mdi-refresh")
|
110
|
+
vuetify.VTooltip("Refresh Contents", activator="parent")
|
97
111
|
|
98
112
|
with GridLayout(columns=2, classes="flex-1-0 h-0", valign="start"):
|
99
113
|
if not self._prefix:
|
@@ -185,6 +199,9 @@ class DataSelector(datagrid.VGrid):
|
|
185
199
|
|
186
200
|
self._vm.update_view()
|
187
201
|
|
202
|
+
def refresh_contents(self) -> None:
|
203
|
+
self._vm.update_view(refresh_directories=True)
|
204
|
+
|
188
205
|
def reset(self, _: Any = None) -> None:
|
189
206
|
self._reset_state()
|
190
207
|
self._reset_rv_grid()
|
@@ -194,3 +211,11 @@ class DataSelector(datagrid.VGrid):
|
|
194
211
|
"The old DataSelector component has been renamed to NeutronDataSelector. Please import it from "
|
195
212
|
"`nova.trame.view.components.ornl`."
|
196
213
|
)
|
214
|
+
|
215
|
+
async def _refresh_loop(self) -> None:
|
216
|
+
if self._refresh_rate > 0:
|
217
|
+
while True:
|
218
|
+
await sleep(self._refresh_rate)
|
219
|
+
|
220
|
+
self.refresh_contents()
|
221
|
+
self.state.dirty(self._datafiles_name)
|
@@ -32,6 +32,7 @@ class NeutronDataSelector(DataSelector):
|
|
32
32
|
instrument: str = "",
|
33
33
|
extensions: Optional[List[str]] = None,
|
34
34
|
prefix: str = "",
|
35
|
+
refresh_rate: int = 30,
|
35
36
|
select_strategy: str = "all",
|
36
37
|
**kwargs: Any,
|
37
38
|
) -> None:
|
@@ -54,6 +55,9 @@ class NeutronDataSelector(DataSelector):
|
|
54
55
|
prefix : str, optional
|
55
56
|
A subdirectory within the user's chosen experiment to show files. If not specified, the user will be shown a
|
56
57
|
folder browser and will be able to see all files in the experiment that they have access to.
|
58
|
+
refresh_rate : int, optional
|
59
|
+
The number of seconds between attempts to automatically refresh the file list. Set to zero to disable this
|
60
|
+
feature. Defaults to 30 seconds.
|
57
61
|
select_strategy : str, optional
|
58
62
|
The selection strategy to pass to the `VDataTable component <https://trame.readthedocs.io/en/latest/trame.widgets.vuetify3.html#trame.widgets.vuetify3.VDataTable>`__.
|
59
63
|
If unset, the `all` strategy will be used.
|
@@ -76,7 +80,7 @@ class NeutronDataSelector(DataSelector):
|
|
76
80
|
self._instruments_name = f"nova__neutrondataselector_{self._next_id}_instruments"
|
77
81
|
self._experiments_name = f"nova__neutrondataselector_{self._next_id}_experiments"
|
78
82
|
|
79
|
-
super().__init__(v_model, "", extensions, prefix, select_strategy, **kwargs)
|
83
|
+
super().__init__(v_model, "", extensions, prefix, refresh_rate, select_strategy, **kwargs)
|
80
84
|
|
81
85
|
def create_ui(self, **kwargs: Any) -> None:
|
82
86
|
super().create_ui(**kwargs)
|
@@ -16,7 +16,7 @@ class DataSelectorViewModel:
|
|
16
16
|
|
17
17
|
self.datafiles: List[Dict[str, Any]] = []
|
18
18
|
self.directories: List[Dict[str, Any]] = []
|
19
|
-
self.expanded: List[str] =
|
19
|
+
self.expanded: Dict[str, List[str]] = {}
|
20
20
|
|
21
21
|
self.state_bind = binding.new_bind(self.model.state, callback_after_update=self.on_state_updated)
|
22
22
|
self.directories_bind = binding.new_bind()
|
@@ -44,9 +44,16 @@ class DataSelectorViewModel:
|
|
44
44
|
current_level["children"] = new_directories
|
45
45
|
|
46
46
|
# Mark this directory as expanded and display the new content
|
47
|
-
self.expanded
|
47
|
+
self.expanded[paths[-1]] = paths
|
48
48
|
self.directories_bind.update_in_view(self.directories)
|
49
49
|
|
50
|
+
def reexpand_directories(self) -> None:
|
51
|
+
paths_to_expand = self.expanded.values()
|
52
|
+
self.expanded = {}
|
53
|
+
|
54
|
+
for paths in paths_to_expand:
|
55
|
+
self.expand_directory(paths)
|
56
|
+
|
50
57
|
def on_state_updated(self, results: Dict[str, Any]) -> None:
|
51
58
|
pass
|
52
59
|
|
@@ -54,10 +61,11 @@ class DataSelectorViewModel:
|
|
54
61
|
self.model.set_subdirectory(subdirectory_path)
|
55
62
|
self.update_view()
|
56
63
|
|
57
|
-
def update_view(self) -> None:
|
64
|
+
def update_view(self, refresh_directories: bool = False) -> None:
|
58
65
|
self.state_bind.update_in_view(self.model.state)
|
59
|
-
if not self.directories:
|
66
|
+
if not self.directories or refresh_directories:
|
60
67
|
self.directories = self.model.get_directories()
|
68
|
+
self.reexpand_directories()
|
61
69
|
self.directories_bind.update_in_view(self.directories)
|
62
70
|
|
63
71
|
self.datafiles = [
|
@@ -25,7 +25,7 @@ class NeutronDataSelectorViewModel(DataSelectorViewModel):
|
|
25
25
|
def reset(self) -> None:
|
26
26
|
self.model.set_subdirectory("")
|
27
27
|
self.directories = self.model.get_directories()
|
28
|
-
self.expanded =
|
28
|
+
self.expanded = {}
|
29
29
|
self.reset_bind.update_in_view(None)
|
30
30
|
|
31
31
|
def on_state_updated(self, results: Dict[str, Any]) -> None:
|
@@ -43,9 +43,9 @@ class NeutronDataSelectorViewModel(DataSelectorViewModel):
|
|
43
43
|
self.reset()
|
44
44
|
self.update_view()
|
45
45
|
|
46
|
-
def update_view(self) -> None:
|
46
|
+
def update_view(self, refresh_directories: bool = False) -> None:
|
47
47
|
self.facilities_bind.update_in_view(self.model.get_facilities())
|
48
48
|
self.instruments_bind.update_in_view(self.model.get_instruments())
|
49
49
|
self.experiments_bind.update_in_view(self.model.get_experiments())
|
50
50
|
|
51
|
-
super().update_view()
|
51
|
+
super().update_view(refresh_directories)
|
@@ -1,15 +1,15 @@
|
|
1
1
|
nova/__init__.py,sha256=ED6jHcYiuYpr_0vjGz0zx2lrrmJT9sDJCzIljoDfmlM,65
|
2
2
|
nova/trame/__init__.py,sha256=gFrAg1qva5PIqR5TjvPzAxLx103IKipJLqp3XXvrQL8,59
|
3
|
-
nova/trame/model/data_selector.py,sha256=
|
3
|
+
nova/trame/model/data_selector.py,sha256=8eaIVGak6XOAQMxdUotOsiXisW14sSRd1V0oViglJVQ,4448
|
4
4
|
nova/trame/model/ornl/neutron_data_selector.py,sha256=nfjXwT93JcPjJwyDynoP_stDVAfjUs7neeVZTk_04gc,6424
|
5
5
|
nova/trame/model/remote_file_input.py,sha256=9KAf31ZHzpsh_aXUrNcF81Q5jvUZDWCzW1QATKls-Jk,3675
|
6
6
|
nova/trame/view/components/__init__.py,sha256=60BeS69aOrFnkptjuD17rfPE1f4Z35iBH56TRmW5MW8,451
|
7
|
-
nova/trame/view/components/data_selector.py,sha256=
|
7
|
+
nova/trame/view/components/data_selector.py,sha256=d5UDF7ENBNifmLyIecx8VyINRY4vSxlQHyJ2a5G7IOY,9606
|
8
8
|
nova/trame/view/components/execution_buttons.py,sha256=fIkrWKI3jFZqk3GHhtmYh3nK2c-HOXpD3D3zd_TUpi0,4049
|
9
9
|
nova/trame/view/components/file_upload.py,sha256=7VcpfA6zmiqMDLkwVPlb35Tf0IUTBN1xsHpoUFnSr1w,3111
|
10
10
|
nova/trame/view/components/input_field.py,sha256=q6WQ_N-BOlimUL9zgazDlsDfK28FrrKjH4he8e_HzRA,16088
|
11
11
|
nova/trame/view/components/ornl/__init__.py,sha256=HnxzzSsxw0vQSDCVFfWsAxx1n3HnU37LMuQkfiewmSU,90
|
12
|
-
nova/trame/view/components/ornl/neutron_data_selector.py,sha256=
|
12
|
+
nova/trame/view/components/ornl/neutron_data_selector.py,sha256=8B0BVXzVtMApnbMGD6ms6G4gdv5l-dIWM6YlHcBgnoc,6878
|
13
13
|
nova/trame/view/components/progress_bar.py,sha256=fCfPw4MPAvORaeFOXugreok4GLpDVZGMkqvnv-AhMxg,2967
|
14
14
|
nova/trame/view/components/remote_file_input.py,sha256=ByrBFj8svyWezcardCWrS_4Ag3fgTYNg_11lDW1FIA8,9669
|
15
15
|
nova/trame/view/components/tool_outputs.py,sha256=-6pDURd2l_FK_8EWa9BI3KhU_KJXJ6uyJ_rW4nQVc08,2337
|
@@ -31,14 +31,14 @@ nova/trame/view/theme/assets/vuetify_config.json,sha256=a0FSgpLYWGFlRGSMhMq61MyD
|
|
31
31
|
nova/trame/view/theme/exit_button.py,sha256=Kqv1GVJZGrSsj6_JFjGU3vm3iNuMolLC2T1x2IsdmV0,3094
|
32
32
|
nova/trame/view/theme/theme.py,sha256=8JqSrEbhxK1SccXE1_jUdel9Wtc2QNObVEwtbVWG_QY,13146
|
33
33
|
nova/trame/view/utilities/local_storage.py,sha256=vD8f2VZIpxhIKjZwEaD7siiPCTZO4cw9AfhwdawwYLY,3218
|
34
|
-
nova/trame/view_model/data_selector.py,sha256=
|
34
|
+
nova/trame/view_model/data_selector.py,sha256=yDyYceZAUIxv4hhJGAPdIo54zHmrwqkxNZh7F2sRlw0,2810
|
35
35
|
nova/trame/view_model/execution_buttons.py,sha256=MfKSp95D92EqpD48C15cBo6dLO0Yld4FeRZMJNxJf7Y,3551
|
36
|
-
nova/trame/view_model/ornl/neutron_data_selector.py,sha256=
|
36
|
+
nova/trame/view_model/ornl/neutron_data_selector.py,sha256=WTuz9QO4WzbOftTH0uP9Qxn7nYdsnIoixu1hWHKCVNU,2128
|
37
37
|
nova/trame/view_model/progress_bar.py,sha256=6AUKHF3hfzbdsHqNEnmHRgDcBKY5TT8ywDx9S6ovnsc,2854
|
38
38
|
nova/trame/view_model/remote_file_input.py,sha256=ojEOJ8ZPkajpbAaZi9VLj7g-uBjhb8BMrTdMmwf_J6A,3367
|
39
39
|
nova/trame/view_model/tool_outputs.py,sha256=ev6LY7fJ0H2xAJn9f5ww28c8Kpom2SYc2FbvFcoN4zg,829
|
40
|
-
nova_trame-0.23.
|
41
|
-
nova_trame-0.23.
|
42
|
-
nova_trame-0.23.
|
43
|
-
nova_trame-0.23.
|
44
|
-
nova_trame-0.23.
|
40
|
+
nova_trame-0.23.1.dist-info/LICENSE,sha256=Iu5QiDbwNbREg75iYaxIJ_V-zppuv4QFuBhAW-qiAlM,1061
|
41
|
+
nova_trame-0.23.1.dist-info/METADATA,sha256=VVMLgB8JhBIzt_FbCAEUIjPh3Zu8gEqQy091t3Fpd8E,1688
|
42
|
+
nova_trame-0.23.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
43
|
+
nova_trame-0.23.1.dist-info/entry_points.txt,sha256=J2AmeSwiTYZ4ZqHHp9HO6v4MaYQTTBPbNh6WtoqOT58,42
|
44
|
+
nova_trame-0.23.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|