@@ -102,13 +102,15 @@ let lastVisualPayload = null;
102102let isGeneratingCalendar = false ;
103103const GENERATE_BUTTON_DEFAULT_LABEL = 'Generate schedule' ;
104104const GENERATE_BUTTON_LOADING_LABEL = 'Generating…' ;
105+ const VISUALS_EMPTY_STATE_MESSAGE = 'No schedule generated yet. Click Generate to create one.' ;
105106
106107const CALENDAR_HISTORY_LIMIT = 50 ;
107108const calendarHistoryState = {
108109 runHistory : [ ] ,
109110 panel : null ,
110111 list : null ,
111112 activeId : null ,
113+ currentEntry : null ,
112114 summaryContainer : null ,
113115 summaryList : null ,
114116 summaryMeta : null ,
@@ -217,6 +219,13 @@ function hideVisualsOverlay() {
217219 text . textContent = '' ;
218220}
219221
222+ function showVisualsEmptyState ( ) {
223+ if ( isGeneratingCalendar ) {
224+ return ;
225+ }
226+ showVisualsOverlay ( VISUALS_EMPTY_STATE_MESSAGE , { loading : false } ) ;
227+ }
228+
220229function resolveLegacyPng ( payload ) {
221230 if ( ! payload || typeof payload !== 'object' ) {
222231 return '' ;
@@ -381,6 +390,11 @@ function safeInitVisuals(initialData) {
381390 const payload = lastVisualPayload ?? ( initialData && typeof initialData === 'object' ? initialData : null ) ;
382391 console . info ( '[visuals] initializing with' , hasVisualEvents ( payload ) ? 'real data' : 'no data' ) ;
383392 updateVisuals ( payload ) ;
393+ if ( hasVisualEvents ( payload ) ) {
394+ hideVisualsOverlay ( ) ;
395+ } else {
396+ showVisualsEmptyState ( ) ;
397+ }
384398 } catch ( error ) {
385399 console . error ( '[visuals] init failed:' , error ) ;
386400 }
@@ -559,6 +573,8 @@ function renderCalendarRunHistory() {
559573 list . append ( emptyItem ) ;
560574 updateActiveRunLabel ( ) ;
561575 renderCalendarHistorySummary ( ) ;
576+ updateVisuals ( null ) ;
577+ showVisualsEmptyState ( ) ;
562578 return ;
563579 }
564580
@@ -638,9 +654,16 @@ function renderCalendarHistorySummary() {
638654 return ;
639655 }
640656
641- const { activeId, runHistory } = calendarHistoryState ;
657+ const { activeId, runHistory, currentEntry } = calendarHistoryState ;
642658 const activeIndex = activeId ? runHistory . findIndex ( ( entry ) => entry . id === activeId ) : - 1 ;
643- if ( activeIndex === - 1 ) {
659+ const entry =
660+ currentEntry && currentEntry . id === activeId
661+ ? currentEntry
662+ : activeIndex !== - 1
663+ ? runHistory [ activeIndex ]
664+ : null ;
665+
666+ if ( ! entry ) {
644667 list . innerHTML = '' ;
645668 if ( meta ) {
646669 meta . textContent = '' ;
@@ -649,7 +672,6 @@ function renderCalendarHistorySummary() {
649672 return ;
650673 }
651674
652- const entry = runHistory [ activeIndex ] ;
653675 const summary = ensureCalendarHistorySummary ( entry ) ;
654676
655677 list . innerHTML = '' ;
@@ -691,8 +713,13 @@ function renderCalendarHistorySummary() {
691713 } ) ;
692714
693715 if ( meta ) {
694- const runNumber = runHistory . length - activeIndex ;
695- const metaParts = [ `Run #${ runNumber } ` ] ;
716+ const runNumber = activeIndex !== - 1 ? runHistory . length - activeIndex : null ;
717+ const metaParts = [ ] ;
718+ if ( Number . isFinite ( runNumber ) ) {
719+ metaParts . push ( `Run #${ runNumber } ` ) ;
720+ } else {
721+ metaParts . push ( 'Run' ) ;
722+ }
696723 if ( entry . weekStart ) {
697724 metaParts . push ( `Week ${ entry . weekStart } ` ) ;
698725 }
@@ -706,6 +733,51 @@ function renderCalendarHistorySummary() {
706733 container . hidden = false ;
707734}
708735
736+ function setCurrentCalendarHistoryEntry ( entry , options = { } ) {
737+ const { updateJson = true , focusVisuals = false , showEmptyState = true } = options ;
738+
739+ const payload = entry && entry . rawResult ? cloneCalendarHistoryPayload ( entry . rawResult ) || entry . rawResult : null ;
740+
741+ if ( ! entry || ! payload || typeof payload !== 'object' ) {
742+ calendarHistoryState . activeId = null ;
743+ calendarHistoryState . currentEntry = null ;
744+ updateVisuals ( null ) ;
745+ if ( showEmptyState ) {
746+ showVisualsEmptyState ( ) ;
747+ }
748+ } else {
749+ calendarHistoryState . activeId = entry . id ;
750+ calendarHistoryState . currentEntry = {
751+ ...entry ,
752+ summary : entry . summary && typeof entry . summary === 'object' ? { ...entry . summary } : null ,
753+ rawResult : cloneCalendarHistoryPayload ( payload ) || payload ,
754+ } ;
755+
756+ if ( updateJson ) {
757+ setJsonPayload ( payload , {
758+ variant : entry . variant ,
759+ rig : entry . rig ,
760+ weekStart : entry . weekStart ,
761+ } ) ;
762+ const validation = validateWebV1Calendar ( payload ) ;
763+ setJsonValidationBadge ( validation . ok ? 'ok' : 'err' ) ;
764+ } else {
765+ updateVisuals ( payload ) ;
766+ }
767+
768+ hideVisualsOverlay ( ) ;
769+ }
770+
771+ renderCalendarRunHistory ( ) ;
772+
773+ if ( focusVisuals ) {
774+ dispatchIntent ( {
775+ type : INTENT_TYPES . NAVIGATE_TAB ,
776+ payload : { tab : 'visuals' } ,
777+ } ) ;
778+ }
779+ }
780+
709781function ensureCalendarHistoryPanel ( parentElement ) {
710782 if ( ! parentElement ) {
711783 return null ;
@@ -794,8 +866,7 @@ function recordCalendarHistoryEntry(entry) {
794866 0 ,
795867 CALENDAR_HISTORY_LIMIT ,
796868 ) ;
797- calendarHistoryState . activeId = normalized . id ;
798- renderCalendarRunHistory ( ) ;
869+ setCurrentCalendarHistoryEntry ( normalized , { updateJson : false } ) ;
799870}
800871
801872function restoreCalendarHistoryEntry ( entryId ) {
@@ -806,27 +877,7 @@ function restoreCalendarHistoryEntry(entryId) {
806877 if ( ! entry ) {
807878 return ;
808879 }
809- const payload = cloneCalendarHistoryPayload ( entry . rawResult ) || entry . rawResult ;
810- if ( ! payload || typeof payload !== 'object' ) {
811- return ;
812- }
813-
814- calendarHistoryState . activeId = entry . id ;
815-
816- setJsonPayload ( payload , {
817- variant : entry . variant ,
818- rig : entry . rig ,
819- weekStart : entry . weekStart ,
820- } ) ;
821- updateJsonActionsState ( ) ;
822- const validation = validateWebV1Calendar ( payload ) ;
823- setJsonValidationBadge ( validation . ok ? 'ok' : 'err' ) ;
824- renderCalendarRunHistory ( ) ;
825- hideVisualsOverlay ( ) ;
826- dispatchIntent ( {
827- type : INTENT_TYPES . NAVIGATE_TAB ,
828- payload : { tab : 'visuals' } ,
829- } ) ;
880+ setCurrentCalendarHistoryEntry ( entry , { focusVisuals : true } ) ;
830881}
831882
832883let getConfigSnapshot = ( ) => ( {
@@ -1184,6 +1235,11 @@ function setJsonPayload(payload, options = {}) {
11841235 updateJsonActionsState ( ) ;
11851236 updateJsonSummaryDisplay ( ) ;
11861237 updateVisuals ( parsedPayload ) ;
1238+ if ( hasVisualEvents ( parsedPayload ) ) {
1239+ hideVisualsOverlay ( ) ;
1240+ } else if ( ! calendarHistoryState . currentEntry && calendarHistoryState . runHistory . length === 0 ) {
1241+ showVisualsEmptyState ( ) ;
1242+ }
11871243}
11881244
11891245loadRunHistoryFromStorage ( ) ;
@@ -2349,6 +2405,7 @@ async function handleGenerate(event) {
23492405 updateVisuals ( null ) ;
23502406 showVisualsOverlay ( 'Generating schedule…' , { loading : true } ) ;
23512407 calendarHistoryState . activeId = null ;
2408+ calendarHistoryState . currentEntry = null ;
23522409 renderCalendarRunHistory ( ) ;
23532410
23542411 beginConsoleRun ( 'Generating payload…' , { autoSwitch : false } ) ;
0 commit comments