@@ -307,7 +307,7 @@ <h5 class="mb-2">No models in this dataset yet</h5>
307307 </ div >
308308 < div class ="card-body p-0 panel-body position-relative ">
309309 < textarea id ="uvlEditor " class ="d-none "> {% if uvl_content %}{{ uvl_content }}{% endif %}</ textarea >
310- < div id ="uvlSkeleton " class ="uvl-skeleton d-none p-4 ">
310+ < div id ="uvlSkeleton " class ="uvl-skeleton {% if not selected_file %} d-none {% endif %} p-4 ">
311311 < span class ="skeleton skeleton-line " style ="width: 25%; "> </ span >
312312 < span class ="skeleton skeleton-line " style ="width: 55%; margin-left: 1rem; "> </ span >
313313 < span class ="skeleton skeleton-line " style ="width: 40%; margin-left: 2rem; "> </ span >
@@ -380,7 +380,7 @@ <h5 class="mb-2">No models in this dataset yet</h5>
380380 < div class ="card-body panel-body ">
381381 < div id ="FMFactLabelWrapper " class ="w-100 position-relative ">
382382 < svg id ="FMFactLabelChart " class ="chart w-100 " preserveAspectRatio ="xMinYMin meet "> </ svg >
383- < div id ="factLabelSkeleton " class ="factlabel-skeleton d-none ">
383+ < div id ="factLabelSkeleton " class ="factlabel-skeleton {% if not selected_file %} d-none{% endif %} ">
384384 < span class ="skeleton skeleton-line xl mb-3 " style ="width: 50%; "> </ span >
385385 < span class ="skeleton skeleton-line " style ="width: 80%; "> </ span >
386386 < span class ="skeleton skeleton-line " style ="width: 65%; "> </ span >
@@ -617,6 +617,12 @@ <h5 class="fw-bold text-primary mb-0" id="metricModalLabel">Metric Details</h5>
617617 .uvl-skeleton { min-height : 360px ; }
618618 .uvl-skeleton .skeleton-line { font-family : monospace; }
619619 .workbench-panels .CodeMirror .is-loading { visibility : hidden; }
620+ /* Overlay the UVL skeleton on top of the (hidden) CodeMirror so the
621+ panel doesn't double its height while the file is loading. */
622+ .panel-section [data-panel-key = "uvl" ] .panel-body { min-height : 360px ; }
623+ .panel-section [data-panel-key = "uvl" ] # uvlSkeleton {
624+ position : absolute; inset : 0 ; z-index : 2 ;
625+ }
620626</ style >
621627
622628< script >
@@ -675,13 +681,15 @@ <h5 class="fw-bold text-primary mb-0" id="metricModalLabel">Metric Details</h5>
675681 initDescriptionToggle ( ) ;
676682 if ( currentFileId ) {
677683 applyFileUi ( findModel ( currentFileId ) ) ;
678- renderFactLabelForCurrentFile ( ) ;
684+ fetchAndApplyContent ( currentFileId ) ;
679685 }
680686 }
681687 initTooltips ( ) ;
682688} ) ;
683689
684690// ---------- Editor ----------
691+ const UVL_PLAIN_THRESHOLD_BYTES = 1024 * 1024 ; // 1 MB: above this, skip syntax highlighting
692+
685693function initUvlEditor ( ) {
686694 const ta = document . getElementById ( 'uvlEditor' ) ;
687695 if ( ! ta || ! window . CodeMirror ) return ;
@@ -694,9 +702,32 @@ <h5 class="fw-bold text-primary mb-0" id="metricModalLabel">Metric Details</h5>
694702 indentUnit : 2 ,
695703 lineWrapping : false ,
696704 foldGutter : true ,
697- gutters : [ "CodeMirror-linenumbers" , "CodeMirror-foldgutter" ] ,
698- viewportMargin : Infinity
705+ gutters : [ "CodeMirror-linenumbers" , "CodeMirror-foldgutter" ]
699706 } ) ;
707+ // Hide CodeMirror until the async fetch lands content; the skeleton
708+ // (rendered visible by the template) carries the visual.
709+ if ( currentFileId ) setUvlLoading ( true ) ;
710+ }
711+
712+ function applyUvlContent ( text ) {
713+ if ( ! uvlEditorInstance ) {
714+ setUvlLoading ( false ) ;
715+ return ;
716+ }
717+ const big = ( text || '' ) . length > UVL_PLAIN_THRESHOLD_BYTES ;
718+ uvlEditorInstance . setOption ( 'mode' , big ? null : 'uvl' ) ;
719+ // Defer setValue so the loading skeleton paints first; CodeMirror's
720+ // setValue can block the main thread for several seconds on large files.
721+ setTimeout ( ( ) => {
722+ try {
723+ if ( uvlEditorInstance ) {
724+ uvlEditorInstance . setValue ( text || '' ) ;
725+ uvlEditorInstance . refresh ( ) ;
726+ }
727+ } finally {
728+ setUvlLoading ( false ) ;
729+ }
730+ } , 0 ) ;
700731}
701732
702733// ---------- Panel collapsing ----------
@@ -954,11 +985,7 @@ <h5 class="fw-bold text-primary mb-0" id="metricModalLabel">Metric Details</h5>
954985 fetch ( url , { credentials : 'same-origin' } )
955986 . then ( r => r . ok ? r . json ( ) : Promise . reject ( r . status ) )
956987 . then ( data => {
957- if ( uvlEditorInstance ) {
958- uvlEditorInstance . setValue ( data . uvl || '' ) ;
959- uvlEditorInstance . refresh ( ) ;
960- setTimeout ( ( ) => uvlEditorInstance . refresh ( ) , 0 ) ;
961- }
988+ applyUvlContent ( data . uvl || '' ) ;
962989 const ideLink = document . getElementById ( 'workbench-ide-link' ) ;
963990 if ( ideLink ) ideLink . href = data . ide_url ;
964991 const fl = document . getElementById ( 'workbench-factlabel-external' ) ;
@@ -967,11 +994,8 @@ <h5 class="fw-bold text-primary mb-0" id="metricModalLabel">Metric Details</h5>
967994 } )
968995 . catch ( err => {
969996 console . error ( 'workbench fetch error' , err ) ;
970- if ( uvlEditorInstance ) uvlEditorInstance . setValue ( `[Error loading model: ${ err } ]` ) ;
997+ applyUvlContent ( `[Error loading model: ${ err } ]` ) ;
971998 setFactLabelLoading ( false ) ;
972- } )
973- . finally ( ( ) => {
974- setUvlLoading ( false ) ;
975999 } ) ;
9761000}
9771001
0 commit comments