@@ -204,15 +204,19 @@ const sfc = {
204
204
};
205
205
},
206
206
207
- mounted () {
207
+ async mounted () {
208
208
// load job data and then auto-reload periodically
209
- this .loadJob ();
209
+ // need to await first loadJob so this.currentJobStepsStates is initialized and can be used in hashChangeListener
210
+ await this .loadJob ();
210
211
this .intervalID = setInterval (this .loadJob , 1000 );
211
212
document .body .addEventListener (' click' , this .closeDropdown );
213
+ this .hashChangeListener ();
214
+ window .addEventListener (' hashchange' , this .hashChangeListener );
212
215
},
213
216
214
217
beforeUnmount () {
215
218
document .body .removeEventListener (' click' , this .closeDropdown );
219
+ window .removeEventListener (' hashchange' , this .hashChangeListener );
216
220
},
217
221
218
222
unmounted () {
@@ -280,14 +284,16 @@ const sfc = {
280
284
this .fetchPost (` ${ this .run .link } /approve` );
281
285
},
282
286
283
- createLogLine (line , startTime ) {
287
+ createLogLine (line , startTime , stepIndex ) {
284
288
const div = document .createElement (' div' );
285
289
div .classList .add (' job-log-line' );
290
+ div .setAttribute (' id' , ` jobstep-${ stepIndex} -${ line .index } ` );
286
291
div ._jobLogTime = line .timestamp ;
287
292
288
- const lineNumber = document .createElement (' div ' );
289
- lineNumber .className = ' line-num' ;
293
+ const lineNumber = document .createElement (' a ' );
294
+ lineNumber .classList . add ( ' line-num' , ' muted ' ) ;
290
295
lineNumber .textContent = line .index ;
296
+ lineNumber .setAttribute (' href' , ` #jobstep-${ stepIndex} -${ line .index } ` );
291
297
div .append (lineNumber);
292
298
293
299
// for "Show timestamps"
@@ -318,7 +324,7 @@ const sfc = {
318
324
for (const line of logLines) {
319
325
// TODO: group support: ##[group]GroupTitle , ##[endgroup]
320
326
const el = this .getLogsContainer (stepIndex);
321
- el .append (this .createLogLine (line, startTime));
327
+ el .append (this .createLogLine (line, startTime, stepIndex ));
322
328
}
323
329
},
324
330
@@ -429,6 +435,21 @@ const sfc = {
429
435
} else {
430
436
actionBodyEl .append (fullScreenEl);
431
437
}
438
+ },
439
+ async hashChangeListener () {
440
+ const selectedLogStep = window .location .hash ;
441
+ if (! selectedLogStep) return ;
442
+ const [_ , step , _line ] = selectedLogStep .split (' -' );
443
+ if (! this .currentJobStepsStates [step]) return ;
444
+ if (! this .currentJobStepsStates [step].expanded && this .currentJobStepsStates [step].cursor === null ) {
445
+ this .currentJobStepsStates [step].expanded = true ;
446
+ // need to await for load job if the step log is loaded for the first time
447
+ // so logline can be selected by querySelector
448
+ await this .loadJob ();
449
+ }
450
+ const logLine = this .$refs .steps .querySelector (selectedLogStep);
451
+ if (! logLine) return ;
452
+ logLine .querySelector (' .line-num' ).click ();
432
453
}
433
454
},
434
455
};
@@ -802,10 +823,15 @@ export function initRepositoryActionView() {
802
823
display: flex;
803
824
}
804
825
805
- .job - step- section .job - step- logs .job - log- line: hover {
826
+ .job - log- line: hover,
827
+ .job - log- line: target {
806
828
background- color: var (-- color- console - hover- bg);
807
829
}
808
830
831
+ .job - log- line: target {
832
+ scroll- margin- top: 95px ;
833
+ }
834
+
809
835
/* class names 'log-time-seconds' and 'log-time-stamp' are used in the method toggleTimeDisplay */
810
836
.job - log- line .line - num, .log - time- seconds {
811
837
width: 48px ;
@@ -814,6 +840,11 @@ export function initRepositoryActionView() {
814
840
user- select: none;
815
841
}
816
842
843
+ .job - log- line: target > .line - num {
844
+ color: var (-- color- primary);
845
+ text- decoration: underline;
846
+ }
847
+
817
848
.log - time- seconds {
818
849
padding- right: 2px ;
819
850
}
0 commit comments