cjm-transcript-source-select 0.0.29__tar.gz → 0.0.31__tar.gz
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.
- {cjm_transcript_source_select-0.0.29/cjm_transcript_source_select.egg-info → cjm_transcript_source_select-0.0.31}/PKG-INFO +83 -57
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/README.md +77 -51
- cjm_transcript_source_select-0.0.31/cjm_transcript_source_select/__init__.py +1 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/_modidx.py +2 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/source_browser.py +54 -18
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/step_renderer.py +46 -22
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/models.py +5 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/filtering.py +1 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/init.py +10 -2
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/local_files.py +4 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/queue.py +1 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/source_browser.py +30 -2
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/tabs.py +2 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31/cjm_transcript_source_select.egg-info}/PKG-INFO +83 -57
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select.egg-info/requires.txt +5 -5
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/pyproject.toml +1 -1
- cjm_transcript_source_select-0.0.29/cjm_transcript_source_select/__init__.py +0 -1
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/LICENSE +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/MANIFEST.in +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/__init__.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/helpers.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/local_files.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/preview_panel.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/components/selection_queue.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/html_ids.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/__init__.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/routes/core.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/services/__init__.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/services/source.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/services/source_utils.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select/utils.py +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select.egg-info/SOURCES.txt +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select.egg-info/dependency_links.txt +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select.egg-info/entry_points.txt +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/cjm_transcript_source_select.egg-info/top_level.txt +0 -0
- {cjm_transcript_source_select-0.0.29 → cjm_transcript_source_select-0.0.31}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cjm-transcript-source-select
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.31
|
|
4
4
|
Summary: FastHTML source selection component for transcript decomposition workflows, with federated database browsing, drag-drop ordering, and keyboard navigation.
|
|
5
5
|
Author-email: "Christian J. Mills" <9126128+cj-mills@users.noreply.github.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -15,14 +15,14 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
15
15
|
Requires-Python: >=3.12
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: python-fasthtml
|
|
18
|
+
Requires-Dist: python-fasthtml
|
|
19
19
|
Requires-Dist: cjm-plugin-system
|
|
20
20
|
Requires-Dist: cjm-transcription-plugin-system
|
|
21
|
-
Requires-Dist: cjm-fasthtml-app-core
|
|
21
|
+
Requires-Dist: cjm-fasthtml-app-core>=0.0.17
|
|
22
22
|
Requires-Dist: cjm-fasthtml-daisyui
|
|
23
23
|
Requires-Dist: cjm_fasthtml_lucide_icons
|
|
24
|
-
Requires-Dist: cjm_fasthtml_file_browser>=0.0.
|
|
25
|
-
Requires-Dist: cjm_fasthtml_keyboard_navigation>=0.0.
|
|
24
|
+
Requires-Dist: cjm_fasthtml_file_browser>=0.0.19
|
|
25
|
+
Requires-Dist: cjm_fasthtml_keyboard_navigation>=0.0.23
|
|
26
26
|
Requires-Dist: duckdb
|
|
27
27
|
Requires-Dist: pandas
|
|
28
28
|
Requires-Dist: cjm_workflow_state
|
|
@@ -30,7 +30,7 @@ Requires-Dist: cjm_source_provider
|
|
|
30
30
|
Requires-Dist: cjm_fasthtml_interactions
|
|
31
31
|
Requires-Dist: cjm_fasthtml_viewport_fit
|
|
32
32
|
Requires-Dist: cjm_fasthtml_virtual_collection
|
|
33
|
-
Requires-Dist: cjm_fasthtml_sortable_queue>=0.0.
|
|
33
|
+
Requires-Dist: cjm_fasthtml_sortable_queue>=0.0.16
|
|
34
34
|
Requires-Dist: cjm_fasthtml_design_system>=0.0.9
|
|
35
35
|
Dynamic: license-file
|
|
36
36
|
|
|
@@ -96,57 +96,57 @@ graph LR
|
|
|
96
96
|
utils[utils<br/>utils]
|
|
97
97
|
|
|
98
98
|
components_helpers --> models
|
|
99
|
-
components_local_files --> components_helpers
|
|
100
99
|
components_local_files --> html_ids
|
|
100
|
+
components_local_files --> components_helpers
|
|
101
101
|
components_preview_panel --> html_ids
|
|
102
102
|
components_source_browser --> services_source_utils
|
|
103
103
|
components_source_browser --> html_ids
|
|
104
104
|
components_source_browser --> utils
|
|
105
|
-
components_step_renderer --> components_preview_panel
|
|
106
|
-
components_step_renderer --> utils
|
|
107
105
|
components_step_renderer --> components_selection_queue
|
|
108
|
-
components_step_renderer --> components_source_browser
|
|
109
|
-
components_step_renderer --> models
|
|
110
106
|
components_step_renderer --> html_ids
|
|
107
|
+
components_step_renderer --> models
|
|
111
108
|
components_step_renderer --> components_local_files
|
|
112
|
-
|
|
109
|
+
components_step_renderer --> components_source_browser
|
|
110
|
+
components_step_renderer --> components_preview_panel
|
|
111
|
+
components_step_renderer --> utils
|
|
113
112
|
routes_core --> models
|
|
114
|
-
routes_core --> components_selection_queue
|
|
115
|
-
routes_core --> services_source
|
|
116
113
|
routes_core --> html_ids
|
|
117
|
-
|
|
114
|
+
routes_core --> components_step_renderer
|
|
115
|
+
routes_core --> services_source
|
|
116
|
+
routes_core --> components_selection_queue
|
|
118
117
|
routes_filtering --> services_source_utils
|
|
119
118
|
routes_filtering --> services_source
|
|
119
|
+
routes_filtering --> routes_core
|
|
120
120
|
routes_filtering --> models
|
|
121
|
-
routes_init --> routes_local_files
|
|
122
|
-
routes_init --> routes_source_browser
|
|
123
121
|
routes_init --> routes_core
|
|
122
|
+
routes_init --> services_source
|
|
123
|
+
routes_init --> routes_local_files
|
|
124
124
|
routes_init --> routes_queue
|
|
125
125
|
routes_init --> routes_tabs
|
|
126
|
-
routes_init --> services_source
|
|
127
|
-
routes_init --> routes_filtering
|
|
128
126
|
routes_init --> models
|
|
129
|
-
|
|
127
|
+
routes_init --> routes_filtering
|
|
128
|
+
routes_init --> routes_source_browser
|
|
130
129
|
routes_local_files --> components_local_files
|
|
131
130
|
routes_local_files --> services_source
|
|
131
|
+
routes_local_files --> routes_core
|
|
132
132
|
routes_local_files --> models
|
|
133
|
-
routes_queue --> components_preview_panel
|
|
134
|
-
routes_queue --> routes_core
|
|
135
|
-
routes_queue --> services_source_utils
|
|
136
133
|
routes_queue --> services_source
|
|
134
|
+
routes_queue --> services_source_utils
|
|
135
|
+
routes_queue --> routes_core
|
|
137
136
|
routes_queue --> models
|
|
138
|
-
|
|
139
|
-
routes_source_browser --> components_source_browser
|
|
137
|
+
routes_queue --> components_preview_panel
|
|
140
138
|
routes_source_browser --> services_source
|
|
141
|
-
routes_source_browser -->
|
|
139
|
+
routes_source_browser --> components_source_browser
|
|
140
|
+
routes_source_browser --> html_ids
|
|
142
141
|
routes_source_browser --> models
|
|
143
142
|
routes_source_browser --> services_source_utils
|
|
144
|
-
routes_source_browser -->
|
|
145
|
-
|
|
143
|
+
routes_source_browser --> routes_core
|
|
144
|
+
routes_source_browser --> components_preview_panel
|
|
145
|
+
routes_tabs --> models
|
|
146
146
|
routes_tabs --> routes_core
|
|
147
|
-
routes_tabs -->
|
|
147
|
+
routes_tabs --> services_source
|
|
148
148
|
routes_tabs --> services_source_utils
|
|
149
|
-
routes_tabs -->
|
|
149
|
+
routes_tabs --> components_step_renderer
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
*52 cross-module dependencies detected*
|
|
@@ -525,12 +525,6 @@ def _handle_remove_external_source(
|
|
|
525
525
|
|
|
526
526
|
``` python
|
|
527
527
|
def init_local_files_router(
|
|
528
|
-
state_store: WorkflowStateStore, # The workflow state store
|
|
529
|
-
workflow_id: str, # The workflow identifier
|
|
530
|
-
source_service: SourceService, # The source service for external db ops
|
|
531
|
-
prefix: str, # Route prefix (e.g., "/workflow/selection/local_files")
|
|
532
|
-
urls: SelectionUrls, # URL bundle for rendering
|
|
533
|
-
) -> LocalFilesResult: # Router result with routers, routes, render, restore, and reset
|
|
534
528
|
"Initialize local files browser routes with new file browser API."
|
|
535
529
|
```
|
|
536
530
|
|
|
@@ -615,6 +609,7 @@ class LocalFilesResult:
|
|
|
615
609
|
render_panel: Callable # (error_message?, session_id?) -> rendered panel
|
|
616
610
|
restore_state: Callable = field(...) # (session_id) -> None, restore persisted state
|
|
617
611
|
reset_state: Callable = field(...) # () -> None, reset in-memory caches
|
|
612
|
+
kb_manager: Optional[ZoneManager] # ZoneManager backing the local file browser's keyboard system — hand to render_keyboard_hints_modal(..., child_managers=[...]) for hierarchical hint display
|
|
618
613
|
```
|
|
619
614
|
|
|
620
615
|
``` python
|
|
@@ -629,6 +624,7 @@ class SelectionResult:
|
|
|
629
624
|
sb_state: Any # SourceBrowserRouterState
|
|
630
625
|
restore_state: Callable = field(...) # (session_id) -> None, restore persisted state
|
|
631
626
|
reset_state: Callable = field(...) # () -> None, reset in-memory caches
|
|
627
|
+
fb_kb_manager: Optional[ZoneManager] # ZoneManager from the local file browser; convenience pointer mirroring LocalFilesResult.kb_manager so step renderers can read it directly from SelectionResult without descending into LocalFilesResult
|
|
632
628
|
```
|
|
633
629
|
|
|
634
630
|
### preview_panel (`preview_panel.ipynb`)
|
|
@@ -1067,7 +1063,8 @@ from cjm_transcript_source_select.components.source_browser import (
|
|
|
1067
1063
|
build_source_items,
|
|
1068
1064
|
is_source_item_skippable,
|
|
1069
1065
|
create_source_cell_renderer,
|
|
1070
|
-
render_source_empty
|
|
1066
|
+
render_source_empty,
|
|
1067
|
+
build_source_browser_keyboard_system
|
|
1071
1068
|
)
|
|
1072
1069
|
```
|
|
1073
1070
|
|
|
@@ -1128,19 +1125,45 @@ def render_source_empty() -> Any: # Empty state component
|
|
|
1128
1125
|
"Render empty state when no transcription sources are available."
|
|
1129
1126
|
```
|
|
1130
1127
|
|
|
1128
|
+
``` python
|
|
1129
|
+
def build_source_browser_keyboard_system(
|
|
1130
|
+
sb_state: Any, # SourceBrowserRouterState (carries vc_ids, vc_btn_ids, vc_urls)
|
|
1131
|
+
manager_label: Optional[str] = None, # Human-readable label for the ZoneManager (consumed by render_keyboard_hints_modal section header when this is a child_managers entry)
|
|
1132
|
+
) -> KeyboardSystem: # Complete rendered KeyboardSystem (carries .manager for hierarchical hints handoff)
|
|
1133
|
+
"""
|
|
1134
|
+
Build the source browser's KeyboardSystem standalone.
|
|
1135
|
+
|
|
1136
|
+
Lifts the manager construction out of `_render_source_browser_vc_content`
|
|
1137
|
+
so the underlying `ZoneManager` is accessible via `KeyboardSystem.manager`
|
|
1138
|
+
for hierarchical hints handoff. Consumers wiring this as a child of the
|
|
1139
|
+
parent selection-step manager pass the manager to
|
|
1140
|
+
`render_keyboard_hints_modal(..., child_managers=[...])` so the modal's
|
|
1141
|
+
section header reads as `manager_label` instead of the technical SB_SYSTEM_ID.
|
|
1142
|
+
"""
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1131
1145
|
``` python
|
|
1132
1146
|
def _render_source_browser_vc_content(
|
|
1133
|
-
sb_state: Any,
|
|
1147
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
1148
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system (when None, builds internally via build_source_browser_keyboard_system)
|
|
1134
1149
|
) -> Any: # VC content wrapper (without search/grouping header)
|
|
1135
|
-
"
|
|
1150
|
+
"""
|
|
1151
|
+
Render the VC content portion of the source browser.
|
|
1152
|
+
|
|
1153
|
+
When `keyboard_system` is provided, the caller has built the system upstream
|
|
1154
|
+
(typically `init_source_browser_router`) and owns the underlying ZoneManager.
|
|
1155
|
+
When None, builds the system internally — preserves pre-C1 behavior for any
|
|
1156
|
+
caller that doesn't need the manager handoff.
|
|
1157
|
+
"""
|
|
1136
1158
|
```
|
|
1137
1159
|
|
|
1138
1160
|
``` python
|
|
1139
1161
|
def _render_source_browser_vc(
|
|
1140
|
-
sb_state: Any,
|
|
1141
|
-
filter_url: str = "",
|
|
1142
|
-
grouping_mode: str = "media_path",
|
|
1143
|
-
grouping_change_url: str = "",
|
|
1162
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
1163
|
+
filter_url: str = "", # URL for filtering sources
|
|
1164
|
+
grouping_mode: str = "media_path", # Current grouping mode
|
|
1165
|
+
grouping_change_url: str = "", # URL for changing grouping mode
|
|
1166
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system, threaded through to VC content
|
|
1144
1167
|
) -> Any: # Source browser component with virtual collection
|
|
1145
1168
|
"Render the full source browser panel (header + VC content)."
|
|
1146
1169
|
```
|
|
@@ -1187,10 +1210,6 @@ from cjm_transcript_source_select.routes.source_browser import (
|
|
|
1187
1210
|
|
|
1188
1211
|
``` python
|
|
1189
1212
|
def init_source_browser_router(
|
|
1190
|
-
source_service: SourceService, # Source service for querying transcriptions
|
|
1191
|
-
urls: SelectionUrls, # URL bundle (toggle, select_all, filter, grouping_change)
|
|
1192
|
-
prefix: str = "/browser", # Route prefix for VC routes
|
|
1193
|
-
) -> SourceBrowserRouterState: # Router state with all VC objects and helpers
|
|
1194
1213
|
"Initialize the source browser virtual collection router."
|
|
1195
1214
|
```
|
|
1196
1215
|
|
|
@@ -1215,6 +1234,7 @@ class SourceBrowserRouterState:
|
|
|
1215
1234
|
get_visible_checkbox_oobs: Callable # () -> tuple of OOB elements
|
|
1216
1235
|
get_checkbox_oob_for: Callable # (record_id, provider_id) -> OOB element or None
|
|
1217
1236
|
get_vc_row_id_for: Callable # (record_id, provider_id) -> str or None
|
|
1237
|
+
kb_manager: Optional[ZoneManager] # ZoneManager backing the source browser's VC keyboard system — hand to render_keyboard_hints_modal(..., child_managers=[...]) for hierarchical hint display
|
|
1218
1238
|
```
|
|
1219
1239
|
|
|
1220
1240
|
### source_utils (`source_utils.ipynb`)
|
|
@@ -1381,7 +1401,22 @@ from cjm_transcript_source_select.components.step_renderer import (
|
|
|
1381
1401
|
|
|
1382
1402
|
``` python
|
|
1383
1403
|
def _create_parent_keyboard_manager() -> ZoneManager: # Parent keyboard manager for hierarchy
|
|
1384
|
-
"
|
|
1404
|
+
"""
|
|
1405
|
+
Create the parent keyboard manager with two ghost zones for column switching.
|
|
1406
|
+
|
|
1407
|
+
Each ghost zone declares `activate_child_callback` so the library-baked
|
|
1408
|
+
Enter/Space dispatch (`ZoneManager.activate_keys` defaults to `("Enter", " ")`)
|
|
1409
|
+
invokes the consumer-defined JS function — `window.activateBrowserChild`
|
|
1410
|
+
and `window.activateQueueChild` are wired in `_generate_hierarchy_js`. The
|
|
1411
|
+
callback path is used (vs. the declarative `activate_child_id` path) because
|
|
1412
|
+
the browser ghost zone's active child depends on the currently-selected
|
|
1413
|
+
tab (`db` → source-browser child; `files` → file-browser child); this
|
|
1414
|
+
dynamic resolution can't be a static declarative mapping.
|
|
1415
|
+
|
|
1416
|
+
Each ghost zone's `label` surfaces as the section header for that zone's
|
|
1417
|
+
derived rows in the hints modal (e.g., the parent's "Source Browser" /
|
|
1418
|
+
"Selection Queue" — Activate row appears under those labels).
|
|
1419
|
+
"""
|
|
1385
1420
|
```
|
|
1386
1421
|
|
|
1387
1422
|
``` python
|
|
@@ -1428,15 +1463,6 @@ def _generate_hierarchy_js(
|
|
|
1428
1463
|
|
|
1429
1464
|
``` python
|
|
1430
1465
|
def render_selection_step(
|
|
1431
|
-
sources: List[Dict[str, Any]], # Available source plugins
|
|
1432
|
-
transcriptions: List[Dict[str, Any]], # Available transcription records
|
|
1433
|
-
selected_sources: List[Dict[str, str]], # Ordered selection
|
|
1434
|
-
grouping_mode: str, # Grouping mode: "media_path" or "batch_id"
|
|
1435
|
-
active_tab: str, # Active tab: "db" or "files"
|
|
1436
|
-
urls: SelectionUrls, # URL bundle for selection routes
|
|
1437
|
-
render_local_files_panel: Optional[Callable] = None, # Render fn for Files tab content
|
|
1438
|
-
sb_state: Any = None, # SourceBrowserRouterState for DB tab VC rendering
|
|
1439
|
-
) -> Any: # FastHTML component
|
|
1440
1466
|
"Render Phase 1: Source Selection & Ordering step with two-column layout."
|
|
1441
1467
|
```
|
|
1442
1468
|
|
|
@@ -60,57 +60,57 @@ graph LR
|
|
|
60
60
|
utils[utils<br/>utils]
|
|
61
61
|
|
|
62
62
|
components_helpers --> models
|
|
63
|
-
components_local_files --> components_helpers
|
|
64
63
|
components_local_files --> html_ids
|
|
64
|
+
components_local_files --> components_helpers
|
|
65
65
|
components_preview_panel --> html_ids
|
|
66
66
|
components_source_browser --> services_source_utils
|
|
67
67
|
components_source_browser --> html_ids
|
|
68
68
|
components_source_browser --> utils
|
|
69
|
-
components_step_renderer --> components_preview_panel
|
|
70
|
-
components_step_renderer --> utils
|
|
71
69
|
components_step_renderer --> components_selection_queue
|
|
72
|
-
components_step_renderer --> components_source_browser
|
|
73
|
-
components_step_renderer --> models
|
|
74
70
|
components_step_renderer --> html_ids
|
|
71
|
+
components_step_renderer --> models
|
|
75
72
|
components_step_renderer --> components_local_files
|
|
76
|
-
|
|
73
|
+
components_step_renderer --> components_source_browser
|
|
74
|
+
components_step_renderer --> components_preview_panel
|
|
75
|
+
components_step_renderer --> utils
|
|
77
76
|
routes_core --> models
|
|
78
|
-
routes_core --> components_selection_queue
|
|
79
|
-
routes_core --> services_source
|
|
80
77
|
routes_core --> html_ids
|
|
81
|
-
|
|
78
|
+
routes_core --> components_step_renderer
|
|
79
|
+
routes_core --> services_source
|
|
80
|
+
routes_core --> components_selection_queue
|
|
82
81
|
routes_filtering --> services_source_utils
|
|
83
82
|
routes_filtering --> services_source
|
|
83
|
+
routes_filtering --> routes_core
|
|
84
84
|
routes_filtering --> models
|
|
85
|
-
routes_init --> routes_local_files
|
|
86
|
-
routes_init --> routes_source_browser
|
|
87
85
|
routes_init --> routes_core
|
|
86
|
+
routes_init --> services_source
|
|
87
|
+
routes_init --> routes_local_files
|
|
88
88
|
routes_init --> routes_queue
|
|
89
89
|
routes_init --> routes_tabs
|
|
90
|
-
routes_init --> services_source
|
|
91
|
-
routes_init --> routes_filtering
|
|
92
90
|
routes_init --> models
|
|
93
|
-
|
|
91
|
+
routes_init --> routes_filtering
|
|
92
|
+
routes_init --> routes_source_browser
|
|
94
93
|
routes_local_files --> components_local_files
|
|
95
94
|
routes_local_files --> services_source
|
|
95
|
+
routes_local_files --> routes_core
|
|
96
96
|
routes_local_files --> models
|
|
97
|
-
routes_queue --> components_preview_panel
|
|
98
|
-
routes_queue --> routes_core
|
|
99
|
-
routes_queue --> services_source_utils
|
|
100
97
|
routes_queue --> services_source
|
|
98
|
+
routes_queue --> services_source_utils
|
|
99
|
+
routes_queue --> routes_core
|
|
101
100
|
routes_queue --> models
|
|
102
|
-
|
|
103
|
-
routes_source_browser --> components_source_browser
|
|
101
|
+
routes_queue --> components_preview_panel
|
|
104
102
|
routes_source_browser --> services_source
|
|
105
|
-
routes_source_browser -->
|
|
103
|
+
routes_source_browser --> components_source_browser
|
|
104
|
+
routes_source_browser --> html_ids
|
|
106
105
|
routes_source_browser --> models
|
|
107
106
|
routes_source_browser --> services_source_utils
|
|
108
|
-
routes_source_browser -->
|
|
109
|
-
|
|
107
|
+
routes_source_browser --> routes_core
|
|
108
|
+
routes_source_browser --> components_preview_panel
|
|
109
|
+
routes_tabs --> models
|
|
110
110
|
routes_tabs --> routes_core
|
|
111
|
-
routes_tabs -->
|
|
111
|
+
routes_tabs --> services_source
|
|
112
112
|
routes_tabs --> services_source_utils
|
|
113
|
-
routes_tabs -->
|
|
113
|
+
routes_tabs --> components_step_renderer
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
*52 cross-module dependencies detected*
|
|
@@ -489,12 +489,6 @@ def _handle_remove_external_source(
|
|
|
489
489
|
|
|
490
490
|
``` python
|
|
491
491
|
def init_local_files_router(
|
|
492
|
-
state_store: WorkflowStateStore, # The workflow state store
|
|
493
|
-
workflow_id: str, # The workflow identifier
|
|
494
|
-
source_service: SourceService, # The source service for external db ops
|
|
495
|
-
prefix: str, # Route prefix (e.g., "/workflow/selection/local_files")
|
|
496
|
-
urls: SelectionUrls, # URL bundle for rendering
|
|
497
|
-
) -> LocalFilesResult: # Router result with routers, routes, render, restore, and reset
|
|
498
492
|
"Initialize local files browser routes with new file browser API."
|
|
499
493
|
```
|
|
500
494
|
|
|
@@ -579,6 +573,7 @@ class LocalFilesResult:
|
|
|
579
573
|
render_panel: Callable # (error_message?, session_id?) -> rendered panel
|
|
580
574
|
restore_state: Callable = field(...) # (session_id) -> None, restore persisted state
|
|
581
575
|
reset_state: Callable = field(...) # () -> None, reset in-memory caches
|
|
576
|
+
kb_manager: Optional[ZoneManager] # ZoneManager backing the local file browser's keyboard system — hand to render_keyboard_hints_modal(..., child_managers=[...]) for hierarchical hint display
|
|
582
577
|
```
|
|
583
578
|
|
|
584
579
|
``` python
|
|
@@ -593,6 +588,7 @@ class SelectionResult:
|
|
|
593
588
|
sb_state: Any # SourceBrowserRouterState
|
|
594
589
|
restore_state: Callable = field(...) # (session_id) -> None, restore persisted state
|
|
595
590
|
reset_state: Callable = field(...) # () -> None, reset in-memory caches
|
|
591
|
+
fb_kb_manager: Optional[ZoneManager] # ZoneManager from the local file browser; convenience pointer mirroring LocalFilesResult.kb_manager so step renderers can read it directly from SelectionResult without descending into LocalFilesResult
|
|
596
592
|
```
|
|
597
593
|
|
|
598
594
|
### preview_panel (`preview_panel.ipynb`)
|
|
@@ -1031,7 +1027,8 @@ from cjm_transcript_source_select.components.source_browser import (
|
|
|
1031
1027
|
build_source_items,
|
|
1032
1028
|
is_source_item_skippable,
|
|
1033
1029
|
create_source_cell_renderer,
|
|
1034
|
-
render_source_empty
|
|
1030
|
+
render_source_empty,
|
|
1031
|
+
build_source_browser_keyboard_system
|
|
1035
1032
|
)
|
|
1036
1033
|
```
|
|
1037
1034
|
|
|
@@ -1092,19 +1089,45 @@ def render_source_empty() -> Any: # Empty state component
|
|
|
1092
1089
|
"Render empty state when no transcription sources are available."
|
|
1093
1090
|
```
|
|
1094
1091
|
|
|
1092
|
+
``` python
|
|
1093
|
+
def build_source_browser_keyboard_system(
|
|
1094
|
+
sb_state: Any, # SourceBrowserRouterState (carries vc_ids, vc_btn_ids, vc_urls)
|
|
1095
|
+
manager_label: Optional[str] = None, # Human-readable label for the ZoneManager (consumed by render_keyboard_hints_modal section header when this is a child_managers entry)
|
|
1096
|
+
) -> KeyboardSystem: # Complete rendered KeyboardSystem (carries .manager for hierarchical hints handoff)
|
|
1097
|
+
"""
|
|
1098
|
+
Build the source browser's KeyboardSystem standalone.
|
|
1099
|
+
|
|
1100
|
+
Lifts the manager construction out of `_render_source_browser_vc_content`
|
|
1101
|
+
so the underlying `ZoneManager` is accessible via `KeyboardSystem.manager`
|
|
1102
|
+
for hierarchical hints handoff. Consumers wiring this as a child of the
|
|
1103
|
+
parent selection-step manager pass the manager to
|
|
1104
|
+
`render_keyboard_hints_modal(..., child_managers=[...])` so the modal's
|
|
1105
|
+
section header reads as `manager_label` instead of the technical SB_SYSTEM_ID.
|
|
1106
|
+
"""
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1095
1109
|
``` python
|
|
1096
1110
|
def _render_source_browser_vc_content(
|
|
1097
|
-
sb_state: Any,
|
|
1111
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
1112
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system (when None, builds internally via build_source_browser_keyboard_system)
|
|
1098
1113
|
) -> Any: # VC content wrapper (without search/grouping header)
|
|
1099
|
-
"
|
|
1114
|
+
"""
|
|
1115
|
+
Render the VC content portion of the source browser.
|
|
1116
|
+
|
|
1117
|
+
When `keyboard_system` is provided, the caller has built the system upstream
|
|
1118
|
+
(typically `init_source_browser_router`) and owns the underlying ZoneManager.
|
|
1119
|
+
When None, builds the system internally — preserves pre-C1 behavior for any
|
|
1120
|
+
caller that doesn't need the manager handoff.
|
|
1121
|
+
"""
|
|
1100
1122
|
```
|
|
1101
1123
|
|
|
1102
1124
|
``` python
|
|
1103
1125
|
def _render_source_browser_vc(
|
|
1104
|
-
sb_state: Any,
|
|
1105
|
-
filter_url: str = "",
|
|
1106
|
-
grouping_mode: str = "media_path",
|
|
1107
|
-
grouping_change_url: str = "",
|
|
1126
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
1127
|
+
filter_url: str = "", # URL for filtering sources
|
|
1128
|
+
grouping_mode: str = "media_path", # Current grouping mode
|
|
1129
|
+
grouping_change_url: str = "", # URL for changing grouping mode
|
|
1130
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system, threaded through to VC content
|
|
1108
1131
|
) -> Any: # Source browser component with virtual collection
|
|
1109
1132
|
"Render the full source browser panel (header + VC content)."
|
|
1110
1133
|
```
|
|
@@ -1151,10 +1174,6 @@ from cjm_transcript_source_select.routes.source_browser import (
|
|
|
1151
1174
|
|
|
1152
1175
|
``` python
|
|
1153
1176
|
def init_source_browser_router(
|
|
1154
|
-
source_service: SourceService, # Source service for querying transcriptions
|
|
1155
|
-
urls: SelectionUrls, # URL bundle (toggle, select_all, filter, grouping_change)
|
|
1156
|
-
prefix: str = "/browser", # Route prefix for VC routes
|
|
1157
|
-
) -> SourceBrowserRouterState: # Router state with all VC objects and helpers
|
|
1158
1177
|
"Initialize the source browser virtual collection router."
|
|
1159
1178
|
```
|
|
1160
1179
|
|
|
@@ -1179,6 +1198,7 @@ class SourceBrowserRouterState:
|
|
|
1179
1198
|
get_visible_checkbox_oobs: Callable # () -> tuple of OOB elements
|
|
1180
1199
|
get_checkbox_oob_for: Callable # (record_id, provider_id) -> OOB element or None
|
|
1181
1200
|
get_vc_row_id_for: Callable # (record_id, provider_id) -> str or None
|
|
1201
|
+
kb_manager: Optional[ZoneManager] # ZoneManager backing the source browser's VC keyboard system — hand to render_keyboard_hints_modal(..., child_managers=[...]) for hierarchical hint display
|
|
1182
1202
|
```
|
|
1183
1203
|
|
|
1184
1204
|
### source_utils (`source_utils.ipynb`)
|
|
@@ -1345,7 +1365,22 @@ from cjm_transcript_source_select.components.step_renderer import (
|
|
|
1345
1365
|
|
|
1346
1366
|
``` python
|
|
1347
1367
|
def _create_parent_keyboard_manager() -> ZoneManager: # Parent keyboard manager for hierarchy
|
|
1348
|
-
"
|
|
1368
|
+
"""
|
|
1369
|
+
Create the parent keyboard manager with two ghost zones for column switching.
|
|
1370
|
+
|
|
1371
|
+
Each ghost zone declares `activate_child_callback` so the library-baked
|
|
1372
|
+
Enter/Space dispatch (`ZoneManager.activate_keys` defaults to `("Enter", " ")`)
|
|
1373
|
+
invokes the consumer-defined JS function — `window.activateBrowserChild`
|
|
1374
|
+
and `window.activateQueueChild` are wired in `_generate_hierarchy_js`. The
|
|
1375
|
+
callback path is used (vs. the declarative `activate_child_id` path) because
|
|
1376
|
+
the browser ghost zone's active child depends on the currently-selected
|
|
1377
|
+
tab (`db` → source-browser child; `files` → file-browser child); this
|
|
1378
|
+
dynamic resolution can't be a static declarative mapping.
|
|
1379
|
+
|
|
1380
|
+
Each ghost zone's `label` surfaces as the section header for that zone's
|
|
1381
|
+
derived rows in the hints modal (e.g., the parent's "Source Browser" /
|
|
1382
|
+
"Selection Queue" — Activate row appears under those labels).
|
|
1383
|
+
"""
|
|
1349
1384
|
```
|
|
1350
1385
|
|
|
1351
1386
|
``` python
|
|
@@ -1392,15 +1427,6 @@ def _generate_hierarchy_js(
|
|
|
1392
1427
|
|
|
1393
1428
|
``` python
|
|
1394
1429
|
def render_selection_step(
|
|
1395
|
-
sources: List[Dict[str, Any]], # Available source plugins
|
|
1396
|
-
transcriptions: List[Dict[str, Any]], # Available transcription records
|
|
1397
|
-
selected_sources: List[Dict[str, str]], # Ordered selection
|
|
1398
|
-
grouping_mode: str, # Grouping mode: "media_path" or "batch_id"
|
|
1399
|
-
active_tab: str, # Active tab: "db" or "files"
|
|
1400
|
-
urls: SelectionUrls, # URL bundle for selection routes
|
|
1401
|
-
render_local_files_panel: Optional[Callable] = None, # Render fn for Files tab content
|
|
1402
|
-
sb_state: Any = None, # SourceBrowserRouterState for DB tab VC rendering
|
|
1403
|
-
) -> Any: # FastHTML component
|
|
1404
1430
|
"Render Phase 1: Source Selection & Ordering step with two-column layout."
|
|
1405
1431
|
```
|
|
1406
1432
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.31"
|
|
@@ -45,6 +45,8 @@ d = { 'settings': { 'branch': 'main',
|
|
|
45
45
|
'cjm_transcript_source_select/components/source_browser.py'),
|
|
46
46
|
'cjm_transcript_source_select.components.source_browser._render_source_browser_vc_content': ( 'components/source_browser.html#_render_source_browser_vc_content',
|
|
47
47
|
'cjm_transcript_source_select/components/source_browser.py'),
|
|
48
|
+
'cjm_transcript_source_select.components.source_browser.build_source_browser_keyboard_system': ( 'components/source_browser.html#build_source_browser_keyboard_system',
|
|
49
|
+
'cjm_transcript_source_select/components/source_browser.py'),
|
|
48
50
|
'cjm_transcript_source_select.components.source_browser.build_source_items': ( 'components/source_browser.html#build_source_items',
|
|
49
51
|
'cjm_transcript_source_select/components/source_browser.py'),
|
|
50
52
|
'cjm_transcript_source_select.components.source_browser.create_source_cell_renderer': ( 'components/source_browser.html#create_source_cell_renderer',
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# %% auto #0
|
|
6
6
|
__all__ = ['SOURCE_BROWSER_COLUMNS', 'SB_SYSTEM_ID', 'SourceBrowserItem', 'build_source_items', 'is_source_item_skippable',
|
|
7
|
-
'create_source_cell_renderer', 'render_source_empty']
|
|
7
|
+
'create_source_cell_renderer', 'render_source_empty', 'build_source_browser_keyboard_system']
|
|
8
8
|
|
|
9
9
|
# %% ../../nbs/components/source_browser.ipynb #7b2e89c5
|
|
10
10
|
import json
|
|
@@ -53,7 +53,7 @@ from cjm_fasthtml_virtual_collection.js.scrollbar import generate_scrollbar_js
|
|
|
53
53
|
from cjm_fasthtml_virtual_collection.js.auto_fit import generate_auto_fit_js, auto_fit_callback_name
|
|
54
54
|
|
|
55
55
|
from cjm_fasthtml_keyboard_navigation.core.manager import ZoneManager
|
|
56
|
-
from cjm_fasthtml_keyboard_navigation.components.system import render_keyboard_system
|
|
56
|
+
from cjm_fasthtml_keyboard_navigation.components.system import render_keyboard_system, KeyboardSystem
|
|
57
57
|
|
|
58
58
|
from cjm_fasthtml_viewport_fit.models import ViewportFitConfig
|
|
59
59
|
from cjm_fasthtml_viewport_fit.components import render_viewport_fit_script
|
|
@@ -306,10 +306,52 @@ _SB_VC_WRAPPER_ID = "sb-vc-wrapper"
|
|
|
306
306
|
SB_SYSTEM_ID = "sb-collection"
|
|
307
307
|
|
|
308
308
|
|
|
309
|
+
def build_source_browser_keyboard_system(
|
|
310
|
+
sb_state: Any, # SourceBrowserRouterState (carries vc_ids, vc_btn_ids, vc_urls)
|
|
311
|
+
manager_label: Optional[str] = None, # Human-readable label for the ZoneManager (consumed by render_keyboard_hints_modal section header when this is a child_managers entry)
|
|
312
|
+
) -> KeyboardSystem: # Complete rendered KeyboardSystem (carries .manager for hierarchical hints handoff)
|
|
313
|
+
"""Build the source browser's KeyboardSystem standalone.
|
|
314
|
+
|
|
315
|
+
Lifts the manager construction out of `_render_source_browser_vc_content`
|
|
316
|
+
so the underlying `ZoneManager` is accessible via `KeyboardSystem.manager`
|
|
317
|
+
for hierarchical hints handoff. Consumers wiring this as a child of the
|
|
318
|
+
parent selection-step manager pass the manager to
|
|
319
|
+
`render_keyboard_hints_modal(..., child_managers=[...])` so the modal's
|
|
320
|
+
section header reads as `manager_label` instead of the technical SB_SYSTEM_ID.
|
|
321
|
+
"""
|
|
322
|
+
vc_ids = sb_state.ids
|
|
323
|
+
vc_btn_ids = sb_state.btn_ids
|
|
324
|
+
vc_urls = sb_state.urls
|
|
325
|
+
|
|
326
|
+
zone = create_collection_focus_zone(vc_ids)
|
|
327
|
+
nav_actions = create_collection_nav_actions(zone.id, vc_btn_ids)
|
|
328
|
+
manager = ZoneManager(
|
|
329
|
+
zones=(zone,),
|
|
330
|
+
actions=nav_actions,
|
|
331
|
+
system_id=SB_SYSTEM_ID,
|
|
332
|
+
label=manager_label,
|
|
333
|
+
)
|
|
334
|
+
url_map = build_collection_url_map(vc_btn_ids, vc_urls)
|
|
335
|
+
target_map = {btn_id: f"#{vc_ids.rows}" for btn_id in url_map}
|
|
336
|
+
swap_map = {btn_id: "none" for btn_id in url_map}
|
|
337
|
+
kb_system = render_keyboard_system(
|
|
338
|
+
manager, url_map=url_map, target_map=target_map, swap_map=swap_map,
|
|
339
|
+
)
|
|
340
|
+
apply_nav_sync(kb_system, vc_ids)
|
|
341
|
+
return kb_system
|
|
342
|
+
|
|
343
|
+
|
|
309
344
|
def _render_source_browser_vc_content(
|
|
310
|
-
sb_state: Any,
|
|
345
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
346
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system (when None, builds internally via build_source_browser_keyboard_system)
|
|
311
347
|
) -> Any: # VC content wrapper (without search/grouping header)
|
|
312
|
-
"""Render the VC content portion of the source browser.
|
|
348
|
+
"""Render the VC content portion of the source browser.
|
|
349
|
+
|
|
350
|
+
When `keyboard_system` is provided, the caller has built the system upstream
|
|
351
|
+
(typically `init_source_browser_router`) and owns the underlying ZoneManager.
|
|
352
|
+
When None, builds the system internally — preserves pre-C1 behavior for any
|
|
353
|
+
caller that doesn't need the manager handoff.
|
|
354
|
+
"""
|
|
313
355
|
vc_ids = sb_state.ids
|
|
314
356
|
vc_btn_ids = sb_state.btn_ids
|
|
315
357
|
vc_config = sb_state.config
|
|
@@ -323,15 +365,8 @@ def _render_source_browser_vc_content(
|
|
|
323
365
|
render_empty=render_source_empty,
|
|
324
366
|
)
|
|
325
367
|
|
|
326
|
-
# Keyboard system
|
|
327
|
-
|
|
328
|
-
nav_actions = create_collection_nav_actions(zone.id, vc_btn_ids)
|
|
329
|
-
manager = ZoneManager(zones=(zone,), actions=nav_actions, system_id=SB_SYSTEM_ID)
|
|
330
|
-
url_map = build_collection_url_map(vc_btn_ids, vc_urls)
|
|
331
|
-
target_map = {btn_id: f"#{vc_ids.rows}" for btn_id in url_map}
|
|
332
|
-
swap_map = {btn_id: "none" for btn_id in url_map}
|
|
333
|
-
kb_system = render_keyboard_system(manager, url_map=url_map, target_map=target_map, swap_map=swap_map)
|
|
334
|
-
apply_nav_sync(kb_system, vc_ids)
|
|
368
|
+
# Keyboard system — use caller-supplied or build internally.
|
|
369
|
+
kb_system = keyboard_system if keyboard_system is not None else build_source_browser_keyboard_system(sb_state)
|
|
335
370
|
|
|
336
371
|
# Auto-fit JS
|
|
337
372
|
auto_fit_js = generate_auto_fit_js(
|
|
@@ -372,13 +407,14 @@ def _render_source_browser_vc_content(
|
|
|
372
407
|
|
|
373
408
|
|
|
374
409
|
def _render_source_browser_vc(
|
|
375
|
-
sb_state: Any,
|
|
376
|
-
filter_url: str = "",
|
|
377
|
-
grouping_mode: str = "media_path",
|
|
378
|
-
grouping_change_url: str = "",
|
|
410
|
+
sb_state: Any, # SourceBrowserRouterState from routes.source_browser
|
|
411
|
+
filter_url: str = "", # URL for filtering sources
|
|
412
|
+
grouping_mode: str = "media_path", # Current grouping mode
|
|
413
|
+
grouping_change_url: str = "", # URL for changing grouping mode
|
|
414
|
+
keyboard_system: Optional[KeyboardSystem] = None, # Pre-built keyboard system, threaded through to VC content
|
|
379
415
|
) -> Any: # Source browser component with virtual collection
|
|
380
416
|
"""Render the full source browser panel (header + VC content)."""
|
|
381
|
-
vc_content = _render_source_browser_vc_content(sb_state)
|
|
417
|
+
vc_content = _render_source_browser_vc_content(sb_state, keyboard_system=keyboard_system)
|
|
382
418
|
|
|
383
419
|
return Div(
|
|
384
420
|
# Header bar with search and grouping selector
|