Revert change to design. Go back to scrollable page

This commit is contained in:
Filipa Lacerda 2017-07-05 11:32:22 +00:00 committed by Phil Hughes
parent 9e4aef263a
commit 2c1f000e3e
5 changed files with 135 additions and 172 deletions

View File

@ -13,25 +13,21 @@ window.Build = (function () {
this.options = options || $('.js-build-options').data();
this.pageUrl = this.options.pageUrl;
this.buildUrl = this.options.buildUrl;
this.buildStatus = this.options.buildStatus;
this.state = this.options.logState;
this.buildStage = this.options.buildStage;
this.$document = $(document);
this.logBytes = 0;
this.scrollOffsetPadding = 30;
this.hasBeenScrolled = false;
this.updateDropdown = this.updateDropdown.bind(this);
this.getBuildTrace = this.getBuildTrace.bind(this);
this.scrollToBottom = this.scrollToBottom.bind(this);
this.$body = $('body');
this.$buildTrace = $('#build-trace');
this.$buildRefreshAnimation = $('.js-build-refresh');
this.$truncatedInfo = $('.js-truncated-info');
this.$buildTraceOutput = $('.js-build-output');
this.$scrollContainer = $('.js-scroll-container');
this.$topBar = $('.js-top-bar');
// Scroll controllers
this.$scrollTopBtn = $('.js-scroll-up');
@ -63,13 +59,22 @@ window.Build = (function () {
.off('click')
.on('click', this.scrollToBottom.bind(this));
const scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100);
this.scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100);
this.$scrollContainer
$(window)
.off('scroll')
.on('scroll', () => {
this.hasBeenScrolled = true;
scrollThrottled();
const contentHeight = this.$buildTraceOutput.prop('scrollHeight');
if (contentHeight > this.windowSize) {
// means the user did not scroll, the content was updated.
this.windowSize = contentHeight;
} else {
// User scrolled
this.hasBeenScrolled = true;
this.toggleScrollAnimation(false);
}
this.scrollThrottled();
});
$(window)
@ -77,59 +82,73 @@ window.Build = (function () {
.on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
this.updateArtifactRemoveDate();
this.initAffixTopArea();
// eslint-disable-next-line
this.getBuildTrace()
.then(() => this.toggleScroll())
.then(() => {
if (!this.hasBeenScrolled) {
this.scrollToBottom();
}
})
.then(() => this.verifyTopPosition());
this.getBuildTrace();
}
Build.prototype.canScroll = function () {
return (this.$scrollContainer.prop('scrollHeight') - this.scrollOffsetPadding) > this.$scrollContainer.height();
Build.prototype.initAffixTopArea = function () {
/**
If the browser does not support position sticky, it returns the position as static.
If the browser does support sticky, then we allow the browser to handle it, if not
then we default back to Bootstraps affix
**/
if (this.$topBar.css('position') !== 'static') return;
const offsetTop = this.$buildTrace.offset().top;
this.$topBar.affix({
offset: {
top: offsetTop,
},
});
};
Build.prototype.canScroll = function () {
return document.body.scrollHeight > window.innerHeight;
};
/**
* | | Up | Down |
* |--------------------------|----------|----------|
* | on scroll bottom | active | disabled |
* | on scroll top | disabled | active |
* | no scroll | disabled | disabled |
* | on.('scroll') is on top | disabled | active |
* | on('scroll) is on bottom | active | disabled |
*
*/
Build.prototype.toggleScroll = function () {
const currentPosition = this.$scrollContainer.scrollTop();
const bottomScroll = currentPosition + this.$scrollContainer.innerHeight();
const currentPosition = document.body.scrollTop;
const windowHeight = window.innerHeight;
if (this.canScroll()) {
if (currentPosition === 0) {
if (currentPosition > 0 &&
(document.body.scrollHeight - currentPosition !== windowHeight)) {
// User is in the middle of the log
this.toggleDisableButton(this.$scrollTopBtn, false);
this.toggleDisableButton(this.$scrollBottomBtn, false);
} else if (currentPosition === 0) {
// User is at Top of Build Log
this.toggleDisableButton(this.$scrollTopBtn, true);
this.toggleDisableButton(this.$scrollBottomBtn, false);
} else if (bottomScroll === this.$scrollContainer.prop('scrollHeight')) {
} else if (document.body.scrollHeight - currentPosition === windowHeight) {
// User is at the bottom of the build log.
this.toggleDisableButton(this.$scrollTopBtn, false);
this.toggleDisableButton(this.$scrollBottomBtn, true);
} else {
this.toggleDisableButton(this.$scrollTopBtn, false);
this.toggleDisableButton(this.$scrollBottomBtn, false);
}
} else {
this.toggleDisableButton(this.$scrollTopBtn, true);
this.toggleDisableButton(this.$scrollBottomBtn, true);
}
};
Build.prototype.scrollToTop = function () {
this.hasBeenScrolled = true;
this.$scrollContainer.scrollTop(0);
this.toggleScroll();
Build.prototype.scrollDown = function () {
document.body.scrollTop = document.body.scrollHeight;
};
Build.prototype.scrollToBottom = function () {
this.scrollDown();
this.hasBeenScrolled = true;
this.toggleScroll();
};
Build.prototype.scrollToTop = function () {
document.body.scrollTop = 0;
this.hasBeenScrolled = true;
this.$scrollContainer.scrollTop(this.$scrollContainer.prop('scrollHeight'));
this.toggleScroll();
};
@ -142,47 +161,6 @@ window.Build = (function () {
this.$scrollBottomBtn.toggleClass('animate', toggle);
};
/**
* Build trace top position depends on the space ocupied by the elments rendered before
*/
Build.prototype.verifyTopPosition = function () {
const $buildPage = $('.build-page');
const $flashError = $('.alert-wrapper');
const $header = $('.build-header', $buildPage);
const $runnersStuck = $('.js-build-stuck', $buildPage);
const $startsEnvironment = $('.js-environment-container', $buildPage);
const $erased = $('.js-build-erased', $buildPage);
const prependTopDefault = 20;
// header + navigation + margin
let topPostion = 168;
if ($header.length) {
topPostion += $header.outerHeight();
}
if ($runnersStuck.length) {
topPostion += $runnersStuck.outerHeight();
}
if ($startsEnvironment.length) {
topPostion += $startsEnvironment.outerHeight() + prependTopDefault;
}
if ($erased.length) {
topPostion += $erased.outerHeight() + prependTopDefault;
}
if ($flashError.length) {
topPostion += $flashError.outerHeight() + prependTopDefault;
}
this.$buildTrace.css({
top: topPostion,
});
};
Build.prototype.initSidebar = function () {
this.$sidebar = $('.js-build-sidebar');
this.$sidebar.niceScroll();
@ -200,6 +178,8 @@ window.Build = (function () {
this.state = log.state;
}
this.windowSize = this.$buildTraceOutput.prop('scrollHeight');
if (log.append) {
this.$buildTraceOutput.append(log.html);
this.logBytes += log.size;
@ -227,14 +207,7 @@ window.Build = (function () {
}
Build.timeout = setTimeout(() => {
//eslint-disable-next-line
this.getBuildTrace()
.then(() => {
if (!this.hasBeenScrolled) {
this.scrollToBottom();
}
})
.then(() => this.verifyTopPosition());
this.getBuildTrace();
}, 4000);
} else {
this.$buildRefreshAnimation.remove();
@ -247,7 +220,13 @@ window.Build = (function () {
})
.fail(() => {
this.$buildRefreshAnimation.remove();
});
})
.then(() => {
if (!this.hasBeenScrolled) {
this.scrollDown();
}
})
.then(() => this.toggleScroll());
};
Build.prototype.shouldHideSidebarForViewport = function () {
@ -259,14 +238,11 @@ window.Build = (function () {
const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
const $toggleButton = $('.js-sidebar-build-toggle-header');
this.$buildTrace
.toggleClass('sidebar-expanded', shouldShow)
.toggleClass('sidebar-collapsed', shouldHide);
this.$sidebar
.toggleClass('right-sidebar-expanded', shouldShow)
.toggleClass('right-sidebar-collapsed', shouldHide);
$('.js-build-page')
this.$topBar
.toggleClass('sidebar-expanded', shouldShow)
.toggleClass('sidebar-collapsed', shouldHide);
@ -279,17 +255,10 @@ window.Build = (function () {
Build.prototype.sidebarOnResize = function () {
this.toggleSidebar(this.shouldHideSidebarForViewport());
this.verifyTopPosition();
if (this.canScroll()) {
this.toggleScroll();
}
};
Build.prototype.sidebarOnClick = function () {
if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
this.verifyTopPosition();
};
Build.prototype.updateArtifactRemoveDate = function () {

View File

@ -26,14 +26,6 @@ document.addEventListener('DOMContentLoaded', () => {
mounted() {
this.mediator.initBuildClass();
},
updated() {
// Wait for flash message to be appended
Vue.nextTick(() => {
if (this.mediator.build) {
this.mediator.build.verifyTopPosition();
}
});
},
render(createElement) {
return createElement('job-header', {
props: {

View File

@ -37,65 +37,77 @@
}
.build-page {
.sticky {
position: absolute;
left: 0;
right: 0;
.build-trace-container {
position: relative;
}
.build-trace-container {
position: absolute;
top: 225px;
left: 15px;
bottom: 10px;
.build-trace {
background: $black;
color: $gray-darkest;
font-family: $monospace_font;
white-space: pre;
overflow-x: auto;
font-size: 12px;
border-radius: 0;
border: none;
&.sidebar-expanded {
right: 305px;
.bash {
display: block;
}
}
.top-bar {
height: 35px;
display: flex;
justify-content: flex-end;
background: $gray-light;
border: 1px solid $border-color;
color: $gl-text-color;
position: sticky;
position: -webkit-sticky;
top: 50px;
&.affix {
top: 50px;
}
&.sidebar-collapsed {
// with sidebar
&.affix.sidebar-expanded {
right: 306px;
left: 16px;
}
// without sidebar
&.affix.sidebar-collapsed {
right: 16px;
left: 16px;
}
code {
background: $black;
color: $gray-darkest;
&.affix-top {
position: absolute;
right: 0;
left: 0;
}
.top-bar {
top: 0;
height: 35px;
display: flex;
justify-content: flex-end;
background: $gray-light;
border: 1px solid $border-color;
color: $gl-text-color;
.truncated-info {
margin: 0 auto;
align-self: center;
.truncated-info {
margin: 0 auto;
align-self: center;
.truncated-info-size {
margin: 0 5px;
}
.truncated-info-size {
margin: 0 5px;
}
.raw-link {
color: $gl-text-color;
margin-left: 5px;
text-decoration: underline;
}
.raw-link {
color: $gl-text-color;
margin-left: 5px;
text-decoration: underline;
}
}
.controllers {
display: flex;
align-self: center;
font-size: 15px;
margin-bottom: 4px;
justify-content: center;
align-items: center;
svg {
height: 15px;
@ -103,17 +115,9 @@
fill: $gl-text-color;
}
.controllers-buttons,
.btn-scroll {
color: $gl-text-color;
height: 15px;
vertical-align: middle;
padding: 0;
width: 12px;
}
.controllers-buttons {
margin: 1px 10px;
color: $gl-text-color;
margin: 0 10px;
}
.btn-scroll.animate {
@ -143,15 +147,6 @@
}
}
.bash {
top: 35px;
left: 10px;
bottom: 0;
padding: 10px 20px 20px 5px;
white-space: pre-wrap;
overflow: auto;
}
.environment-information {
border: 1px solid $border-color;
padding: 8px $gl-padding 12px;

View File

@ -54,13 +54,14 @@
- else
Job has been erased #{time_ago_with_tooltip(@build.erased_at)}
.build-trace-container#build-trace
.top-bar.sticky
.build-trace-container.prepend-top-default
.top-bar.js-top-bar
.js-truncated-info.truncated-info.hidden<
Showing last
%span.js-truncated-info-size.truncated-info-size><
KiB of log -
%a.js-raw-link.raw-link{ href: raw_namespace_project_job_path(@project.namespace, @project, @build) }>< Complete Raw
.controllers
- if @build.has_trace?
= link_to raw_namespace_project_job_path(@project.namespace, @project, @build),
@ -82,10 +83,12 @@
.has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} }
%button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
= custom_icon('scroll_down')
.bash.sticky.js-scroll-container
%code.js-build-output
%pre.build-trace#build-trace
%code.bash.js-build-output
.build-loader-animation.js-build-refresh
= render "sidebar"
.js-build-options{ data: javascript_build_options }

View File

@ -0,0 +1,4 @@
---
title: Update jobs page output to have a scrollable page
merge_request: 12587
author: