cjm-transcript-segment-align 0.0.6__tar.gz → 0.0.7__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_segment_align-0.0.6/cjm_transcript_segment_align.egg-info → cjm_transcript_segment_align-0.0.7}/PKG-INFO +27 -15
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/README.md +26 -14
- cjm_transcript_segment_align-0.0.7/cjm_transcript_segment_align/__init__.py +1 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/_modidx.py +2 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/components/handlers.py +22 -22
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/components/step_renderer.py +33 -18
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/routes/chrome.py +39 -11
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7/cjm_transcript_segment_align.egg-info}/PKG-INFO +27 -15
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/settings.ini +1 -1
- cjm_transcript_segment_align-0.0.6/cjm_transcript_segment_align/__init__.py +0 -1
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/LICENSE +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/MANIFEST.in +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/components/__init__.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/components/helpers.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/components/keyboard_config.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/html_ids.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/models.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/routes/__init__.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/routes/forced_alignment.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/routes/init.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/services/__init__.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align/services/forced_alignment.py +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/SOURCES.txt +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/dependency_links.txt +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/entry_points.txt +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/not-zip-safe +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/requires.txt +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/cjm_transcript_segment_align.egg-info/top_level.txt +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/pyproject.toml +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/setup.cfg +0 -0
- {cjm_transcript_segment_align-0.0.6 → cjm_transcript_segment_align-0.0.7}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: cjm-transcript-segment-align
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
4
4
|
Summary: FastHTML dual-column text segmentation & VAD alignment UI for transcript decomposition workflows with forced alignment-based text splitting for aligning text segments with VAD chunks.
|
|
5
5
|
Home-page: https://github.com/cj-mills/cjm-transcript-segment-align
|
|
6
6
|
Author: Christian J. Mills
|
|
@@ -79,27 +79,27 @@ graph LR
|
|
|
79
79
|
routes_init[routes.init<br/>routes/init]
|
|
80
80
|
services_forced_alignment[services.forced_alignment<br/>forced_alignment]
|
|
81
81
|
|
|
82
|
-
components_handlers --> components_keyboard_config
|
|
83
82
|
components_handlers --> services_forced_alignment
|
|
84
|
-
components_handlers --> html_ids
|
|
85
83
|
components_handlers --> components_step_renderer
|
|
84
|
+
components_handlers --> components_keyboard_config
|
|
86
85
|
components_handlers --> routes_forced_alignment
|
|
86
|
+
components_handlers --> html_ids
|
|
87
87
|
components_keyboard_config --> html_ids
|
|
88
88
|
components_step_renderer --> components_keyboard_config
|
|
89
89
|
components_step_renderer --> components_helpers
|
|
90
90
|
components_step_renderer --> html_ids
|
|
91
|
-
routes_chrome --> html_ids
|
|
92
91
|
routes_chrome --> components_step_renderer
|
|
93
92
|
routes_chrome --> components_handlers
|
|
94
|
-
|
|
93
|
+
routes_chrome --> html_ids
|
|
95
94
|
routes_forced_alignment --> components_step_renderer
|
|
95
|
+
routes_forced_alignment --> html_ids
|
|
96
|
+
routes_init --> routes_forced_alignment
|
|
97
|
+
routes_init --> routes_chrome
|
|
96
98
|
routes_init --> components_handlers
|
|
99
|
+
routes_init --> components_keyboard_config
|
|
100
|
+
routes_init --> services_forced_alignment
|
|
97
101
|
routes_init --> models
|
|
98
102
|
routes_init --> html_ids
|
|
99
|
-
routes_init --> routes_forced_alignment
|
|
100
|
-
routes_init --> services_forced_alignment
|
|
101
|
-
routes_init --> components_keyboard_config
|
|
102
|
-
routes_init --> routes_chrome
|
|
103
103
|
routes_init --> components_step_renderer
|
|
104
104
|
```
|
|
105
105
|
|
|
@@ -128,6 +128,17 @@ from cjm_transcript_segment_align.routes.chrome import (
|
|
|
128
128
|
|
|
129
129
|
#### Functions
|
|
130
130
|
|
|
131
|
+
``` python
|
|
132
|
+
def _restore_align_auto_nav_js() -> str
|
|
133
|
+
"""
|
|
134
|
+
Generate JS to sync the auto-navigate toggle checkbox with the Web Audio state.
|
|
135
|
+
|
|
136
|
+
After chrome switch re-renders the toolbar, the checkbox starts unchecked.
|
|
137
|
+
This reads the JS state (source of truth) and restores the checkbox.
|
|
138
|
+
Included inside the toolbar OOB so it runs after HTMX inserts the new content.
|
|
139
|
+
"""
|
|
140
|
+
```
|
|
141
|
+
|
|
131
142
|
``` python
|
|
132
143
|
async def _handle_switch_chrome(
|
|
133
144
|
state_store:SQLiteWorkflowStateStore, # State store instance
|
|
@@ -814,16 +825,17 @@ def render_alignment_status(
|
|
|
814
825
|
|
|
815
826
|
``` python
|
|
816
827
|
def render_footer_inner_content(
|
|
817
|
-
|
|
828
|
+
seg_footer:Any, # Segmentation footer content (or None if not initialized)
|
|
829
|
+
align_footer:Any, # Alignment footer content (or None if not initialized)
|
|
818
830
|
segment_count:int, # Number of text segments
|
|
819
831
|
chunk_count:int, # Number of VAD chunks
|
|
820
|
-
) -> Any: # Styled wrapper div with column
|
|
832
|
+
) -> Any: # Styled wrapper div with both column footers and alignment status
|
|
821
833
|
"""
|
|
822
|
-
Render the footer inner content with
|
|
834
|
+
Render the footer inner content with both column footers always present.
|
|
823
835
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
836
|
+
Both footers remain in the DOM so their internal OOB targets (progress
|
|
837
|
+
indicators, source position) are always valid regardless of which column
|
|
838
|
+
is active. This enables cross-zone features like auto-play.
|
|
827
839
|
"""
|
|
828
840
|
```
|
|
829
841
|
|
|
@@ -43,27 +43,27 @@ graph LR
|
|
|
43
43
|
routes_init[routes.init<br/>routes/init]
|
|
44
44
|
services_forced_alignment[services.forced_alignment<br/>forced_alignment]
|
|
45
45
|
|
|
46
|
-
components_handlers --> components_keyboard_config
|
|
47
46
|
components_handlers --> services_forced_alignment
|
|
48
|
-
components_handlers --> html_ids
|
|
49
47
|
components_handlers --> components_step_renderer
|
|
48
|
+
components_handlers --> components_keyboard_config
|
|
50
49
|
components_handlers --> routes_forced_alignment
|
|
50
|
+
components_handlers --> html_ids
|
|
51
51
|
components_keyboard_config --> html_ids
|
|
52
52
|
components_step_renderer --> components_keyboard_config
|
|
53
53
|
components_step_renderer --> components_helpers
|
|
54
54
|
components_step_renderer --> html_ids
|
|
55
|
-
routes_chrome --> html_ids
|
|
56
55
|
routes_chrome --> components_step_renderer
|
|
57
56
|
routes_chrome --> components_handlers
|
|
58
|
-
|
|
57
|
+
routes_chrome --> html_ids
|
|
59
58
|
routes_forced_alignment --> components_step_renderer
|
|
59
|
+
routes_forced_alignment --> html_ids
|
|
60
|
+
routes_init --> routes_forced_alignment
|
|
61
|
+
routes_init --> routes_chrome
|
|
60
62
|
routes_init --> components_handlers
|
|
63
|
+
routes_init --> components_keyboard_config
|
|
64
|
+
routes_init --> services_forced_alignment
|
|
61
65
|
routes_init --> models
|
|
62
66
|
routes_init --> html_ids
|
|
63
|
-
routes_init --> routes_forced_alignment
|
|
64
|
-
routes_init --> services_forced_alignment
|
|
65
|
-
routes_init --> components_keyboard_config
|
|
66
|
-
routes_init --> routes_chrome
|
|
67
67
|
routes_init --> components_step_renderer
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -92,6 +92,17 @@ from cjm_transcript_segment_align.routes.chrome import (
|
|
|
92
92
|
|
|
93
93
|
#### Functions
|
|
94
94
|
|
|
95
|
+
``` python
|
|
96
|
+
def _restore_align_auto_nav_js() -> str
|
|
97
|
+
"""
|
|
98
|
+
Generate JS to sync the auto-navigate toggle checkbox with the Web Audio state.
|
|
99
|
+
|
|
100
|
+
After chrome switch re-renders the toolbar, the checkbox starts unchecked.
|
|
101
|
+
This reads the JS state (source of truth) and restores the checkbox.
|
|
102
|
+
Included inside the toolbar OOB so it runs after HTMX inserts the new content.
|
|
103
|
+
"""
|
|
104
|
+
```
|
|
105
|
+
|
|
95
106
|
``` python
|
|
96
107
|
async def _handle_switch_chrome(
|
|
97
108
|
state_store:SQLiteWorkflowStateStore, # State store instance
|
|
@@ -778,16 +789,17 @@ def render_alignment_status(
|
|
|
778
789
|
|
|
779
790
|
``` python
|
|
780
791
|
def render_footer_inner_content(
|
|
781
|
-
|
|
792
|
+
seg_footer:Any, # Segmentation footer content (or None if not initialized)
|
|
793
|
+
align_footer:Any, # Alignment footer content (or None if not initialized)
|
|
782
794
|
segment_count:int, # Number of text segments
|
|
783
795
|
chunk_count:int, # Number of VAD chunks
|
|
784
|
-
) -> Any: # Styled wrapper div with column
|
|
796
|
+
) -> Any: # Styled wrapper div with both column footers and alignment status
|
|
785
797
|
"""
|
|
786
|
-
Render the footer inner content with
|
|
798
|
+
Render the footer inner content with both column footers always present.
|
|
787
799
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
800
|
+
Both footers remain in the DOM so their internal OOB targets (progress
|
|
801
|
+
indicators, source position) are always valid regardless of which column
|
|
802
|
+
is active. This enables cross-zone features like auto-play.
|
|
791
803
|
"""
|
|
792
804
|
```
|
|
793
805
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.7"
|
|
@@ -73,6 +73,8 @@ d = { 'settings': { 'branch': 'main',
|
|
|
73
73
|
'cjm_transcript_segment_align/models.py')},
|
|
74
74
|
'cjm_transcript_segment_align.routes.chrome': { 'cjm_transcript_segment_align.routes.chrome._handle_switch_chrome': ( 'routes/chrome.html#_handle_switch_chrome',
|
|
75
75
|
'cjm_transcript_segment_align/routes/chrome.py'),
|
|
76
|
+
'cjm_transcript_segment_align.routes.chrome._restore_align_auto_nav_js': ( 'routes/chrome.html#_restore_align_auto_nav_js',
|
|
77
|
+
'cjm_transcript_segment_align/routes/chrome.py'),
|
|
76
78
|
'cjm_transcript_segment_align.routes.chrome.init_chrome_router': ( 'routes/chrome.html#init_chrome_router',
|
|
77
79
|
'cjm_transcript_segment_align/routes/chrome.py')},
|
|
78
80
|
'cjm_transcript_segment_align.routes.forced_alignment': { 'cjm_transcript_segment_align.routes.forced_alignment._handle_fa_toggle': ( 'routes/forced_alignment.html#_handle_fa_toggle',
|
|
@@ -53,6 +53,7 @@ from cjm_transcript_vad_align.routes.core import (
|
|
|
53
53
|
from cjm_transcript_vad_align.routes.handlers import (
|
|
54
54
|
AlignInitResult, _handle_align_init,
|
|
55
55
|
)
|
|
56
|
+
from cjm_transcript_vad_align.components.step_renderer import render_align_footer_content
|
|
56
57
|
from cjm_transcript_vad_align.services.alignment import AlignmentService
|
|
57
58
|
from cjm_transcript_source_select.services.source import SourceService
|
|
58
59
|
|
|
@@ -410,6 +411,7 @@ def create_seg_init_chrome_wrapper(
|
|
|
410
411
|
workflow_state = state_store.get_state(workflow_id, session_id)
|
|
411
412
|
step_states = workflow_state.get("step_states", {})
|
|
412
413
|
seg_state = step_states.get("segmentation", {})
|
|
414
|
+
align_state = step_states.get("alignment", {})
|
|
413
415
|
|
|
414
416
|
# Only save nltk_presplit if not already saved (avoid overwriting on re-init)
|
|
415
417
|
if "nltk_presplit" not in seg_state:
|
|
@@ -418,7 +420,7 @@ def create_seg_init_chrome_wrapper(
|
|
|
418
420
|
workflow_state["step_states"] = step_states
|
|
419
421
|
state_store.update_state(workflow_id, session_id, workflow_state)
|
|
420
422
|
|
|
421
|
-
chunk_count = len(
|
|
423
|
+
chunk_count = len(align_state.get("vad_chunks", []))
|
|
422
424
|
segment_count = len(result.segments)
|
|
423
425
|
|
|
424
426
|
# Build combined KB system with both zones
|
|
@@ -472,12 +474,20 @@ def create_seg_init_chrome_wrapper(
|
|
|
472
474
|
hx_swap_oob="innerHTML"
|
|
473
475
|
)
|
|
474
476
|
|
|
475
|
-
# Footer OOB with alignment status
|
|
477
|
+
# Footer OOB with both column footers + alignment status
|
|
478
|
+
seg_footer = render_seg_footer_content(result.segments, result.focused_index)
|
|
479
|
+
|
|
480
|
+
# Align footer (if alignment is initialized)
|
|
481
|
+
is_align_init = align_state.get("is_initialized", False)
|
|
482
|
+
if is_align_init and align_state.get("vad_chunks"):
|
|
483
|
+
align_chunks = [VADChunk.from_dict(c) for c in align_state["vad_chunks"]]
|
|
484
|
+
align_focused = align_state.get("focused_chunk_index", 0)
|
|
485
|
+
align_footer = render_align_footer_content(align_chunks, align_focused)
|
|
486
|
+
else:
|
|
487
|
+
align_footer = None
|
|
488
|
+
|
|
476
489
|
footer_oob = Div(
|
|
477
|
-
render_footer_inner_content(
|
|
478
|
-
render_seg_footer_content(result.segments, result.focused_index),
|
|
479
|
-
segment_count, chunk_count
|
|
480
|
-
),
|
|
490
|
+
render_footer_inner_content(seg_footer, align_footer, segment_count, chunk_count),
|
|
481
491
|
id=CombinedHtmlIds.SHARED_FOOTER,
|
|
482
492
|
hx_swap_oob="innerHTML"
|
|
483
493
|
)
|
|
@@ -513,11 +523,7 @@ def create_align_init_chrome_wrapper() -> Callable: # Wrapped handler that adds
|
|
|
513
523
|
visible_count:int=5,
|
|
514
524
|
card_width:int=40,
|
|
515
525
|
):
|
|
516
|
-
"""Wrapped align init that adds mini-stats and
|
|
517
|
-
from cjm_transcript_segmentation.components.step_renderer import render_seg_footer_content
|
|
518
|
-
from cjm_fasthtml_tailwind.utilities.typography import font_size as fs
|
|
519
|
-
from cjm_fasthtml_daisyui.utilities.semantic_colors import text_dui as td
|
|
520
|
-
|
|
526
|
+
"""Wrapped align init that adds mini-stats and both footers."""
|
|
521
527
|
# Call pure domain handler
|
|
522
528
|
result: AlignInitResult = await _handle_align_init(
|
|
523
529
|
state_store, workflow_id, source_service, alignment_service,
|
|
@@ -535,21 +541,15 @@ def create_align_init_chrome_wrapper() -> Callable: # Wrapped handler that adds
|
|
|
535
541
|
# Mini-stats badge OOB
|
|
536
542
|
mini_stats_oob = render_align_mini_stats_badge(result.chunks, oob=True)
|
|
537
543
|
|
|
538
|
-
# Footer OOB with
|
|
539
|
-
# unlike sd-alignment-status which is inside the footer and may not exist yet)
|
|
544
|
+
# Footer OOB with both column footers + alignment status
|
|
540
545
|
segments = [TextSegment.from_dict(s) for s in seg_state.get("segments", [])]
|
|
541
|
-
|
|
546
|
+
seg_focused = seg_state.get("focused_index", 0)
|
|
547
|
+
seg_footer = render_seg_footer_content(segments, seg_focused) if segments else None
|
|
542
548
|
|
|
543
|
-
|
|
544
|
-
column_footer = render_seg_footer_content(segments, focused_index)
|
|
545
|
-
else:
|
|
546
|
-
column_footer = Span(
|
|
547
|
-
"Footer with progress and timestamp details will appear here.",
|
|
548
|
-
cls=combine_classes(fs.sm, td.base_content.opacity(50))
|
|
549
|
-
)
|
|
549
|
+
align_footer = render_align_footer_content(result.chunks, 0)
|
|
550
550
|
|
|
551
551
|
footer_oob = Div(
|
|
552
|
-
render_footer_inner_content(
|
|
552
|
+
render_footer_inner_content(seg_footer, align_footer, segment_count, chunk_count),
|
|
553
553
|
id=CombinedHtmlIds.SHARED_FOOTER,
|
|
554
554
|
hx_swap_oob="innerHTML"
|
|
555
555
|
)
|
|
@@ -27,7 +27,7 @@ from cjm_fasthtml_tailwind.utilities.borders import border
|
|
|
27
27
|
from cjm_fasthtml_tailwind.utilities.effects import opacity, ring
|
|
28
28
|
from cjm_fasthtml_tailwind.utilities.transitions_and_animation import transition, duration
|
|
29
29
|
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import (
|
|
30
|
-
flex_display, flex_direction, justify, items, gap, grow
|
|
30
|
+
flex_display, flex_direction, justify, items, gap, grow, flex_wrap
|
|
31
31
|
)
|
|
32
32
|
from cjm_fasthtml_tailwind.core.base import combine_classes
|
|
33
33
|
|
|
@@ -60,6 +60,7 @@ from cjm_transcript_segmentation.components.step_renderer import (
|
|
|
60
60
|
# Alignment composable renderers
|
|
61
61
|
from cjm_transcript_vad_align.components.step_renderer import (
|
|
62
62
|
render_align_column_body, render_align_mini_stats_text,
|
|
63
|
+
render_align_footer_content,
|
|
63
64
|
)
|
|
64
65
|
from cjm_transcript_vad_align.components.card_stack_config import (
|
|
65
66
|
ALIGN_CS_IDS,
|
|
@@ -180,24 +181,26 @@ def render_alignment_status(
|
|
|
180
181
|
)
|
|
181
182
|
|
|
182
183
|
|
|
183
|
-
# Shared footer inner content styling
|
|
184
|
-
_FOOTER_INNER_CLS = combine_classes(flex_display, justify.between, items.center, w.full, gap(4))
|
|
184
|
+
# Shared footer inner content styling — flex-wrap allows vertical stacking on narrow viewports
|
|
185
|
+
_FOOTER_INNER_CLS = combine_classes(flex_display, flex_wrap.wrap, justify.between, items.center, w.full, gap(4))
|
|
185
186
|
|
|
186
187
|
|
|
187
188
|
#| export
|
|
188
189
|
def render_footer_inner_content(
|
|
189
|
-
|
|
190
|
+
seg_footer:Any, # Segmentation footer content (or None if not initialized)
|
|
191
|
+
align_footer:Any, # Alignment footer content (or None if not initialized)
|
|
190
192
|
segment_count:int, # Number of text segments
|
|
191
193
|
chunk_count:int, # Number of VAD chunks
|
|
192
|
-
) -> Any: # Styled wrapper div with column
|
|
193
|
-
"""Render the footer inner content with
|
|
194
|
+
) -> Any: # Styled wrapper div with both column footers and alignment status
|
|
195
|
+
"""Render the footer inner content with both column footers always present.
|
|
194
196
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
197
|
+
Both footers remain in the DOM so their internal OOB targets (progress
|
|
198
|
+
indicators, source position) are always valid regardless of which column
|
|
199
|
+
is active. This enables cross-zone features like auto-play.
|
|
198
200
|
"""
|
|
199
201
|
return Div(
|
|
200
|
-
|
|
202
|
+
seg_footer or Span(),
|
|
203
|
+
align_footer or Span(),
|
|
201
204
|
render_alignment_status(segment_count, chunk_count),
|
|
202
205
|
cls=_FOOTER_INNER_CLS
|
|
203
206
|
)
|
|
@@ -260,18 +263,30 @@ def _render_shared_chrome(
|
|
|
260
263
|
cls=str(p(2))
|
|
261
264
|
)
|
|
262
265
|
|
|
263
|
-
# --- Footer with alignment status ---
|
|
264
|
-
|
|
265
|
-
|
|
266
|
+
# --- Footer with both column footers + alignment status ---
|
|
267
|
+
# Note: seg_state["segments"] and align_state["vad_chunks"] are already deserialized
|
|
268
|
+
# objects from extract_seg_state/extract_alignment_state — don't call from_dict() again
|
|
269
|
+
seg_segments = seg_state.get("segments", []) if seg_state else []
|
|
270
|
+
segment_count = len(seg_segments)
|
|
271
|
+
align_chunks = align_state.get("vad_chunks", []) if align_state else []
|
|
272
|
+
chunk_count = len(align_chunks)
|
|
266
273
|
|
|
267
|
-
|
|
268
|
-
|
|
274
|
+
# Seg footer
|
|
275
|
+
if is_init and seg_segments:
|
|
269
276
|
focused_index = seg_state.get("focused_index", 0)
|
|
270
|
-
|
|
277
|
+
seg_footer = render_seg_footer_content(seg_segments, focused_index)
|
|
278
|
+
else:
|
|
279
|
+
seg_footer = None
|
|
280
|
+
|
|
281
|
+
# Align footer
|
|
282
|
+
is_align_init = align_state is not None and align_state.get("is_initialized", False)
|
|
283
|
+
if is_align_init and align_chunks:
|
|
284
|
+
align_focused = align_state.get("focused_index", 0)
|
|
285
|
+
align_footer = render_align_footer_content(align_chunks, align_focused)
|
|
271
286
|
else:
|
|
272
|
-
|
|
287
|
+
align_footer = None
|
|
273
288
|
|
|
274
|
-
footer_inner = render_footer_inner_content(
|
|
289
|
+
footer_inner = render_footer_inner_content(seg_footer, align_footer, segment_count, chunk_count)
|
|
275
290
|
|
|
276
291
|
footer = Div(
|
|
277
292
|
footer_inner,
|
|
@@ -8,7 +8,7 @@ __all__ = ['DEBUG_SWITCH_CHROME', 'init_chrome_router']
|
|
|
8
8
|
# %% ../../nbs/routes/chrome.ipynb #c3d4e5f6
|
|
9
9
|
from typing import Tuple, Dict, Callable
|
|
10
10
|
|
|
11
|
-
from fasthtml.common import APIRouter, Div
|
|
11
|
+
from fasthtml.common import APIRouter, Div, Script
|
|
12
12
|
|
|
13
13
|
from cjm_fasthtml_card_stack.components.controls import render_width_slider
|
|
14
14
|
from cjm_fasthtml_card_stack.core.constants import DEFAULT_VISIBLE_COUNT, DEFAULT_CARD_WIDTH
|
|
@@ -34,6 +34,7 @@ from cjm_transcript_segmentation.components.card_stack_config import (
|
|
|
34
34
|
from cjm_transcript_vad_align.components.step_renderer import (
|
|
35
35
|
render_align_toolbar, render_align_footer_content,
|
|
36
36
|
)
|
|
37
|
+
from cjm_transcript_vad_align.components.audio_controls import AlignAudioControlIds
|
|
37
38
|
from cjm_transcript_vad_align.components.card_stack_config import (
|
|
38
39
|
ALIGN_CS_CONFIG, ALIGN_CS_IDS,
|
|
39
40
|
)
|
|
@@ -46,11 +47,28 @@ from cjm_transcript_segment_align.components.handlers import (
|
|
|
46
47
|
build_fa_extra_actions, segments_match_presplit,
|
|
47
48
|
)
|
|
48
49
|
|
|
50
|
+
# Web Audio state key for auto-navigate restore
|
|
51
|
+
from cjm_transcript_vad_align.components.callbacks import ALIGN_AUDIO_CONFIG
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
DEBUG_SWITCH_CHROME = False
|
|
52
55
|
|
|
53
56
|
# %% ../../nbs/routes/chrome.ipynb #e5f6a7b8
|
|
57
|
+
def _restore_align_auto_nav_js() -> str:
|
|
58
|
+
"""Generate JS to sync the auto-navigate toggle checkbox with the Web Audio state.
|
|
59
|
+
|
|
60
|
+
After chrome switch re-renders the toolbar, the checkbox starts unchecked.
|
|
61
|
+
This reads the JS state (source of truth) and restores the checkbox.
|
|
62
|
+
Included inside the toolbar OOB so it runs after HTMX inserts the new content.
|
|
63
|
+
"""
|
|
64
|
+
sk = ALIGN_AUDIO_CONFIG.state_key
|
|
65
|
+
toggle_id = AlignAudioControlIds.AUTO_NAV_TOGGLE
|
|
66
|
+
return f"""
|
|
67
|
+
var _cb = document.getElementById('{toggle_id}');
|
|
68
|
+
if (_cb && window.{sk}) _cb.checked = window.{sk}.autoNavigate || false;
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
|
|
54
72
|
async def _handle_switch_chrome(
|
|
55
73
|
state_store:SQLiteWorkflowStateStore, # State store instance
|
|
56
74
|
workflow_id:str, # Workflow identifier
|
|
@@ -80,7 +98,7 @@ async def _handle_switch_chrome(
|
|
|
80
98
|
chunk_count = len(align_state.get("vad_chunks", []))
|
|
81
99
|
|
|
82
100
|
if active_column == "seg":
|
|
83
|
-
# Segmentation chrome
|
|
101
|
+
# Segmentation chrome (toolbar + controls)
|
|
84
102
|
segments = [TextSegment.from_dict(s) for s in seg_state.get("segments", [])]
|
|
85
103
|
history = seg_state.get("history", [])
|
|
86
104
|
focused_index = seg_state.get("focused_index", 0)
|
|
@@ -108,21 +126,31 @@ async def _handle_switch_chrome(
|
|
|
108
126
|
nltk_split_disabled=nltk_disabled,
|
|
109
127
|
)
|
|
110
128
|
controls_content = render_width_slider(SEG_CS_CONFIG, SEG_CS_IDS, card_width=card_width)
|
|
111
|
-
column_footer = render_seg_footer_content(segments, focused_index)
|
|
112
129
|
else:
|
|
113
|
-
# Alignment chrome
|
|
114
|
-
chunks = [VADChunk.from_dict(c) for c in align_state.get("vad_chunks", [])]
|
|
115
|
-
focused_index = align_state.get("focused_chunk_index", 0)
|
|
130
|
+
# Alignment chrome (toolbar with auto-play toggle + controls)
|
|
116
131
|
visible_count = align_state.get("visible_count", 5)
|
|
117
132
|
is_auto_mode = align_state.get("is_auto_mode", False)
|
|
118
133
|
card_width = align_state.get("card_width", 40)
|
|
119
134
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
# Toolbar now includes auto-play toggle internally;
|
|
136
|
+
# restore script syncs checkbox with JS state after re-render
|
|
137
|
+
toolbar_content = Div(
|
|
138
|
+
render_align_toolbar(
|
|
139
|
+
visible_count=visible_count,
|
|
140
|
+
is_auto_mode=is_auto_mode,
|
|
141
|
+
),
|
|
142
|
+
Script(_restore_align_auto_nav_js()),
|
|
123
143
|
)
|
|
124
144
|
controls_content = render_width_slider(ALIGN_CS_CONFIG, ALIGN_CS_IDS, card_width=card_width)
|
|
125
|
-
|
|
145
|
+
|
|
146
|
+
# --- Footer: both column footers always present ---
|
|
147
|
+
seg_segments = [TextSegment.from_dict(s) for s in seg_state.get("segments", [])]
|
|
148
|
+
seg_focused = seg_state.get("focused_index", 0)
|
|
149
|
+
seg_footer = render_seg_footer_content(seg_segments, seg_focused) if seg_segments else None
|
|
150
|
+
|
|
151
|
+
align_chunks = [VADChunk.from_dict(c) for c in align_state.get("vad_chunks", [])]
|
|
152
|
+
align_focused = align_state.get("focused_chunk_index", 0)
|
|
153
|
+
align_footer = render_align_footer_content(align_chunks, align_focused) if align_chunks else None
|
|
126
154
|
|
|
127
155
|
if DEBUG_SWITCH_CHROME:
|
|
128
156
|
print(f"[SWITCH_CHROME] returning OOB swaps for {active_column}")
|
|
@@ -139,7 +167,7 @@ async def _handle_switch_chrome(
|
|
|
139
167
|
hx_swap_oob="innerHTML"
|
|
140
168
|
)
|
|
141
169
|
footer_oob = Div(
|
|
142
|
-
render_footer_inner_content(
|
|
170
|
+
render_footer_inner_content(seg_footer, align_footer, segment_count, chunk_count),
|
|
143
171
|
id=CombinedHtmlIds.SHARED_FOOTER,
|
|
144
172
|
hx_swap_oob="innerHTML"
|
|
145
173
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: cjm-transcript-segment-align
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
4
4
|
Summary: FastHTML dual-column text segmentation & VAD alignment UI for transcript decomposition workflows with forced alignment-based text splitting for aligning text segments with VAD chunks.
|
|
5
5
|
Home-page: https://github.com/cj-mills/cjm-transcript-segment-align
|
|
6
6
|
Author: Christian J. Mills
|
|
@@ -79,27 +79,27 @@ graph LR
|
|
|
79
79
|
routes_init[routes.init<br/>routes/init]
|
|
80
80
|
services_forced_alignment[services.forced_alignment<br/>forced_alignment]
|
|
81
81
|
|
|
82
|
-
components_handlers --> components_keyboard_config
|
|
83
82
|
components_handlers --> services_forced_alignment
|
|
84
|
-
components_handlers --> html_ids
|
|
85
83
|
components_handlers --> components_step_renderer
|
|
84
|
+
components_handlers --> components_keyboard_config
|
|
86
85
|
components_handlers --> routes_forced_alignment
|
|
86
|
+
components_handlers --> html_ids
|
|
87
87
|
components_keyboard_config --> html_ids
|
|
88
88
|
components_step_renderer --> components_keyboard_config
|
|
89
89
|
components_step_renderer --> components_helpers
|
|
90
90
|
components_step_renderer --> html_ids
|
|
91
|
-
routes_chrome --> html_ids
|
|
92
91
|
routes_chrome --> components_step_renderer
|
|
93
92
|
routes_chrome --> components_handlers
|
|
94
|
-
|
|
93
|
+
routes_chrome --> html_ids
|
|
95
94
|
routes_forced_alignment --> components_step_renderer
|
|
95
|
+
routes_forced_alignment --> html_ids
|
|
96
|
+
routes_init --> routes_forced_alignment
|
|
97
|
+
routes_init --> routes_chrome
|
|
96
98
|
routes_init --> components_handlers
|
|
99
|
+
routes_init --> components_keyboard_config
|
|
100
|
+
routes_init --> services_forced_alignment
|
|
97
101
|
routes_init --> models
|
|
98
102
|
routes_init --> html_ids
|
|
99
|
-
routes_init --> routes_forced_alignment
|
|
100
|
-
routes_init --> services_forced_alignment
|
|
101
|
-
routes_init --> components_keyboard_config
|
|
102
|
-
routes_init --> routes_chrome
|
|
103
103
|
routes_init --> components_step_renderer
|
|
104
104
|
```
|
|
105
105
|
|
|
@@ -128,6 +128,17 @@ from cjm_transcript_segment_align.routes.chrome import (
|
|
|
128
128
|
|
|
129
129
|
#### Functions
|
|
130
130
|
|
|
131
|
+
``` python
|
|
132
|
+
def _restore_align_auto_nav_js() -> str
|
|
133
|
+
"""
|
|
134
|
+
Generate JS to sync the auto-navigate toggle checkbox with the Web Audio state.
|
|
135
|
+
|
|
136
|
+
After chrome switch re-renders the toolbar, the checkbox starts unchecked.
|
|
137
|
+
This reads the JS state (source of truth) and restores the checkbox.
|
|
138
|
+
Included inside the toolbar OOB so it runs after HTMX inserts the new content.
|
|
139
|
+
"""
|
|
140
|
+
```
|
|
141
|
+
|
|
131
142
|
``` python
|
|
132
143
|
async def _handle_switch_chrome(
|
|
133
144
|
state_store:SQLiteWorkflowStateStore, # State store instance
|
|
@@ -814,16 +825,17 @@ def render_alignment_status(
|
|
|
814
825
|
|
|
815
826
|
``` python
|
|
816
827
|
def render_footer_inner_content(
|
|
817
|
-
|
|
828
|
+
seg_footer:Any, # Segmentation footer content (or None if not initialized)
|
|
829
|
+
align_footer:Any, # Alignment footer content (or None if not initialized)
|
|
818
830
|
segment_count:int, # Number of text segments
|
|
819
831
|
chunk_count:int, # Number of VAD chunks
|
|
820
|
-
) -> Any: # Styled wrapper div with column
|
|
832
|
+
) -> Any: # Styled wrapper div with both column footers and alignment status
|
|
821
833
|
"""
|
|
822
|
-
Render the footer inner content with
|
|
834
|
+
Render the footer inner content with both column footers always present.
|
|
823
835
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
836
|
+
Both footers remain in the DOM so their internal OOB targets (progress
|
|
837
|
+
indicators, source position) are always valid regardless of which column
|
|
838
|
+
is active. This enables cross-zone features like auto-play.
|
|
827
839
|
"""
|
|
828
840
|
```
|
|
829
841
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.6"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|