@@ -142,17 +142,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
142
142
</v-container >
143
143
144
144
<!-- the log file viewer -->
145
- <v-row
145
+ <div
146
+ ref =" logScroll"
146
147
no-gutters
147
- class =" overflow-auto px-4 pb-2"
148
+ class =" h-100 overflow-auto px-4 pb-2"
148
149
>
149
- <v-col >
150
- < v-skeleton-loader
151
- v-if = " id && file && results.connected == null "
152
- type = " text@5 "
153
- class = " mx-n4 align-content-start "
154
- / >
155
- <template v-else >
150
+ <v-skeleton-loader
151
+ v-if = " id && file && results.connected == null "
152
+ type = " text@5 "
153
+ class = " mx-n4 align-content-start "
154
+ />
155
+ < template v-else >
156
+ <div class = " d-flex flex-column justify-center " >
156
157
<v-alert
157
158
v-if =" results.error"
158
159
type =" error"
@@ -170,24 +171,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
170
171
:logs =" results.lines"
171
172
:timestamps =" timestamps"
172
173
:word-wrap =" wordWrap"
174
+ :autoScroll =" autoScroll"
173
175
/>
174
- </template >
175
- </v-col >
176
- </v-row >
176
+ </div >
177
+ </template >
178
+ </div >
177
179
</v-container >
178
180
</template >
179
181
180
182
<script >
181
- import { ref , computed } from ' vue'
182
- import { usePrevious , whenever } from ' @vueuse/core'
183
+ import { ref , computed , useTemplateRef } from ' vue'
184
+ import { usePrevious , useScroll , whenever } from ' @vueuse/core'
183
185
import { useStore } from ' vuex'
184
186
import {
185
187
mdiClockOutline ,
186
- mdiFileAlertOutline ,
187
188
mdiFolderRefresh ,
188
189
mdiPowerPlugOff ,
189
190
mdiPowerPlug ,
190
191
mdiWrap ,
192
+ mdiFileAlertOutline ,
193
+ mdiMouseMoveDown ,
191
194
} from ' @mdi/js'
192
195
import { btnProps } from ' @/utils/viewToolbar'
193
196
import graphqlMixin from ' @/mixins/graphql'
@@ -380,6 +383,26 @@ export default {
380
383
relativeID .value = value
381
384
}, 500 )
382
385
386
+ /** AutoScroll? */
387
+ const autoScroll = useInitialOptions (' autoScroll' , { props, emit }, true )
388
+ const logScrollEl = useTemplateRef (' logScroll' )
389
+ const { arrivedState , directions } = useScroll (logScrollEl)
390
+ // Turn on autoscroll when user scrolls to bottom:
391
+ whenever (() => arrivedState .bottom && ! arrivedState .top , () => {
392
+ // (when page first loads both top and bottom are true)
393
+ autoScroll .value = true
394
+ })
395
+ // Turn off autoscroll when user scrolls up:
396
+ whenever (() => directions .top , () => {
397
+ if (results .value .lines .length ) {
398
+ autoScroll .value = false
399
+ }
400
+ })
401
+ // When autoscroll is turned off, cancel any smooth scroll in progress:
402
+ whenever (() => ! autoScroll .value , () => {
403
+ logScrollEl .value ? .scrollBy (0 , 0 )
404
+ })
405
+
383
406
/** View toolbar button size */
384
407
const toolbarBtnSize = ' 40'
385
408
@@ -402,36 +425,12 @@ export default {
402
425
jobLog: ref (relativeID .value == null ? 0 : 1 ),
403
426
timestamps,
404
427
wordWrap,
428
+ autoScroll,
405
429
reset,
406
430
debouncedUpdateRelativeID,
407
431
toolbarBtnSize,
408
432
toolbarBtnProps: btnProps (toolbarBtnSize),
409
- }
410
- },
411
-
412
- data () {
413
- return {
414
- controlGroups: [
415
- {
416
- title: ' Log' ,
417
- controls: [
418
- {
419
- title: ' Timestamps' ,
420
- icon: mdiClockOutline,
421
- action: ' toggle' ,
422
- value: this .timestamps ,
423
- key: ' timestamps'
424
- },
425
- {
426
- title: ' Word wrap' ,
427
- icon: mdiWrap,
428
- action: ' toggle' ,
429
- value: this .wordWrap ,
430
- key: ' wordWrap' ,
431
- },
432
- ]
433
- }
434
- ],
433
+ logScrollEl
435
434
}
436
435
},
437
436
@@ -474,6 +473,36 @@ export default {
474
473
}
475
474
}
476
475
return this .workflowId
476
+ },
477
+ controlGroups () {
478
+ return [
479
+ {
480
+ title: ' Log' ,
481
+ controls: [
482
+ {
483
+ title: ' Timestamps' ,
484
+ icon: mdiClockOutline,
485
+ action: ' toggle' ,
486
+ value: this .timestamps ,
487
+ key: ' timestamps'
488
+ },
489
+ {
490
+ title: ' Word wrap' ,
491
+ icon: mdiWrap,
492
+ action: ' toggle' ,
493
+ value: this .wordWrap ,
494
+ key: ' wordWrap' ,
495
+ },
496
+ {
497
+ title: ' Auto scroll' ,
498
+ icon: mdiMouseMoveDown,
499
+ action: ' toggle' ,
500
+ value: this .autoScroll ,
501
+ key: ' autoScroll' ,
502
+ },
503
+ ]
504
+ }
505
+ ]
477
506
}
478
507
},
479
508
@@ -568,15 +597,15 @@ export default {
568
597
this .file = null
569
598
// go back to last chosen job if we are switching back to job logs
570
599
this .relativeID = val ? this .previousRelativeID : null
571
- },
600
+ }
572
601
},
573
602
574
603
// Misc options
575
604
icons: {
576
- mdiFileAlertOutline,
577
605
mdiFolderRefresh,
578
606
mdiPowerPlug,
579
607
mdiPowerPlugOff,
608
+ mdiFileAlertOutline
580
609
}
581
610
}
582
611
< / script>
0 commit comments