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.
@@ -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
- self._layout.filter = html.Div()
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.append(paths[-1])
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,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: nova-trame
3
- Version: 0.23.0
3
+ Version: 0.23.1
4
4
  Summary: A Python Package for injecting curated themes and custom components into Trame applications
5
5
  License: MIT
6
6
  Keywords: NDIP,Python,Trame,Vuetify
@@ -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=jXu2tRmk0sI6fSbBs-bSggEiRw99M5d8NwpvPOk9nDs,4182
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=uahrLdTRKrec-g8L-xIYW0OG_dCnFuKJxq69ROf2c6I,8532
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=RZAowBxRaxlVsHTsukHTX0reveWG1K6ib8zb1kKL9Ow,6631
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=8XBCc12CcQfctOyz5zAOZTIXddKfpzIp8A_yZI-MpFc,2499
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=CtVva_MXWGRG_KclE4ln8XJP_dfy6-5unE3pjEStOpE,2074
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.0.dist-info/LICENSE,sha256=Iu5QiDbwNbREg75iYaxIJ_V-zppuv4QFuBhAW-qiAlM,1061
41
- nova_trame-0.23.0.dist-info/METADATA,sha256=vKtoLVHkJVqpA4yqwZZmjWWoYdPk1avkhUc5B8KuF80,1688
42
- nova_trame-0.23.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
43
- nova_trame-0.23.0.dist-info/entry_points.txt,sha256=J2AmeSwiTYZ4ZqHHp9HO6v4MaYQTTBPbNh6WtoqOT58,42
44
- nova_trame-0.23.0.dist-info/RECORD,,
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,,