22import  {SvgIcon } from  ' ../svg.ts' 
33import  ActionRunStatus  from  ' ./ActionRunStatus.vue' 
44import  {defineComponent , type  PropType } from  ' vue' 
5- import  {createElementFromAttrs , toggleElem } from  ' ../utils/dom.ts' 
5+ import  {addDelegatedEventListener ,  createElementFromAttrs , toggleElem } from  ' ../utils/dom.ts' 
66import  {formatDatetime } from  ' ../utils/time.ts' 
77import  {renderAnsi } from  ' ../render/ansi.ts' 
88import  {POST , DELETE } from  ' ../modules/fetch.ts' 
@@ -188,6 +188,19 @@ export default defineComponent({
188188    //  load job data and then auto-reload periodically 
189189    //  need to await first loadJob so this.currentJobStepsStates is initialized and can be used in hashChangeListener 
190190    await  this .loadJob (); 
191+ 
192+     //  auto-scroll to the bottom of the log group when it is opened 
193+     //  "toggle" event doesn't bubble, so we need to use 'click' event delegation to handle it 
194+     addDelegatedEventListener (this .elStepsContainer (), ' click' ' summary.job-log-group-summary' el , _ ) =>  { 
195+       if  (! this .optionAlwaysAutoScroll ) return ; 
196+       const =  el .closest (' details.job-log-group' as  HTMLDetailsElement ; 
197+       setTimeout (() =>  { 
198+         if  (elJobLogGroup .open  &&  ! isLogElementInViewport (elJobLogGroup )) { 
199+           elJobLogGroup .scrollIntoView ({behavior: ' smooth' ' end'  
200+         } 
201+       }, 0 ); 
202+     }); 
203+ 
191204    this .intervalID  =  setInterval (() =>  this .loadJob (), 1000 ); 
192205    document .body .addEventListener (' click' this .closeDropdown ); 
193206    this .hashChangeListener (); 
@@ -424,9 +437,13 @@ export default defineComponent({
424437      if  (this .menuVisible ) this .menuVisible  =  false ; 
425438    }, 
426439
440+     elStepsContainer():  HTMLElement  { 
441+       return  this .$refs .stepsContainer  as  HTMLElement ; 
442+     }, 
443+ 
427444    toggleTimeDisplay(type :  ' seconds' |  ' stamp'  
428445      this .timeVisible [` log-time-${type } ` ] =  ! this .timeVisible [` log-time-${type } ` ]; 
429-       for  (const of  ( this .$refs . steps   as   HTMLElement ).querySelectorAll (` .log-time-${type } ` )) { 
446+       for  (const of  this .elStepsContainer ( ).querySelectorAll (` .log-time-${type } ` )) { 
430447        toggleElem (el , this .timeVisible [` log-time-${type } ` ]); 
431448      } 
432449    }, 
@@ -448,7 +465,7 @@ export default defineComponent({
448465        //  so logline can be selected by querySelector 
449466        await  this .loadJob (); 
450467      } 
451-       const =  ( this .$refs . steps   as   HTMLElement ).querySelector (selectedLogStep ); 
468+       const =  this .elStepsContainer ( ).querySelector (selectedLogStep ); 
452469      if  (! logLine ) return ; 
453470      logLine .querySelector <HTMLAnchorElement >(' .line-num' click (); 
454471    }, 
@@ -583,7 +600,7 @@ export default defineComponent({
583600            </div >
584601          </div >
585602        </div >
586-         <div  class =" job-step-container" ref =" steps " v-if =" currentJob.steps.length" 
603+         <div  class =" job-step-container" ref =" stepsContainer " v-if =" currentJob.steps.length" 
587604          <div  class =" job-step-section" v-for =" (jobStep, i) in currentJob.steps" :key =" i" 
588605            <div  class =" job-step-summary" @click.stop =" isExpandable(jobStep.status) && toggleStepLogs(i)" :class =" [currentJobStepsStates[i].expanded ? 'selected' : '', isExpandable(jobStep.status) && 'step-expandable']" 
589606              <!--  If the job is done and the job step log is loaded for the first time, show the loading icon
0 commit comments