Merge pull request #507 from coreos-inc/buildmsg
Better UX for build logs when switching focus back to tab
This commit is contained in:
commit
d606a42e39
3 changed files with 56 additions and 35 deletions
|
@ -24,34 +24,41 @@
|
||||||
please check for JavaScript or networking issues and contact support.
|
please check for JavaScript or networking issues and contact support.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="no-logs" ng-if="!logEntries.length && currentBuild.phase == 'waiting'">
|
<div ng-show="!loadError && pollChannel.skipping">
|
||||||
(Waiting for build to start)
|
Refreshing Build Status...
|
||||||
</span>
|
<span class="cor-loader"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="log-container" ng-class="container.type" ng-repeat="container in logEntries">
|
<div ng-show="!pollChannel.skipping">
|
||||||
<div class="container-header" ng-class="container.type == 'phase' ? container.message : ''"
|
<span class="no-logs" ng-if="!logEntries.length && currentBuild.phase == 'waiting'">
|
||||||
ng-switch on="container.type" ng-click="container.logs.toggle()">
|
(Waiting for build to start)
|
||||||
<i class="fa chevron"
|
</span>
|
||||||
ng-class="container.logs.isVisible ? 'fa-chevron-down' : 'fa-chevron-right'"
|
|
||||||
ng-show="hasLogs(container)"></i>
|
|
||||||
<div ng-switch-when="phase">
|
|
||||||
<span class="container-content build-log-phase" phase="container"></span>
|
|
||||||
</div>
|
|
||||||
<div ng-switch-when="error">
|
|
||||||
<span class="container-content build-log-error" error="container" entries="logEntries"></span>
|
|
||||||
</div>
|
|
||||||
<div ng-switch-when="command">
|
|
||||||
<span class="container-content build-log-command" command="container"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Display the entries for the container -->
|
<div class="log-container" ng-class="container.type" ng-repeat="container in logEntries">
|
||||||
<div class="container-logs" ng-show="container.logs.isVisible">
|
<div class="container-header" ng-class="container.type == 'phase' ? container.message : ''"
|
||||||
<div class="log-entry" bindonce ng-repeat="entry in container.logs.visibleEntries">
|
ng-switch on="container.type" ng-click="container.logs.toggle()">
|
||||||
<span class="id" bo-text="$index + container.index + 1" ng-if="!useTimestamps"></span>
|
<i class="fa chevron"
|
||||||
<span class="id" bo-text="formatDatetime(entry.data.datetime)" ng-if="useTimestamps"></span>
|
ng-class="container.logs.isVisible ? 'fa-chevron-down' : 'fa-chevron-right'"
|
||||||
<span class="message" bo-html="processANSI(entry.message, container)"></span>
|
ng-show="hasLogs(container)"></i>
|
||||||
<span class="timestamp" bo-text="formatDatetime(entry.data.datetime)" ng-if="!useTimestamps"></span>
|
<div ng-switch-when="phase">
|
||||||
|
<span class="container-content build-log-phase" phase="container"></span>
|
||||||
|
</div>
|
||||||
|
<div ng-switch-when="error">
|
||||||
|
<span class="container-content build-log-error" error="container" entries="logEntries"></span>
|
||||||
|
</div>
|
||||||
|
<div ng-switch-when="command">
|
||||||
|
<span class="container-content build-log-command" command="container"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Display the entries for the container -->
|
||||||
|
<div class="container-logs" ng-show="container.logs.isVisible">
|
||||||
|
<div class="log-entry" bindonce ng-repeat="entry in container.logs.visibleEntries">
|
||||||
|
<span class="id" bo-text="$index + container.index + 1" ng-if="!useTimestamps"></span>
|
||||||
|
<span class="id" bo-text="formatDatetime(entry.data.datetime)" ng-if="useTimestamps"></span>
|
||||||
|
<span class="message" bo-html="processANSI(entry.message, container)"></span>
|
||||||
|
<span class="timestamp" bo-text="formatDatetime(entry.data.datetime)" ng-if="!useTimestamps"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,7 +28,7 @@ angular.module('quay').directive('buildLogsView', function () {
|
||||||
$scope.currentBuild = null;
|
$scope.currentBuild = null;
|
||||||
$scope.loadError = null;
|
$scope.loadError = null;
|
||||||
|
|
||||||
var pollChannel = null;
|
$scope.pollChannel = null;
|
||||||
|
|
||||||
var appendToTextLog = function(type, message) {
|
var appendToTextLog = function(type, message) {
|
||||||
if (type == 'phase') {
|
if (type == 'phase') {
|
||||||
|
@ -146,14 +146,14 @@ angular.module('quay').directive('buildLogsView', function () {
|
||||||
getBuildStatusAndLogs(build, callback);
|
getBuildStatusAndLogs(build, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
pollChannel = AngularPollChannel.create($scope, conductStatusAndLogRequest, 5 * 1000 /* 5s */);
|
$scope.pollChannel = AngularPollChannel.create($scope, conductStatusAndLogRequest, 5 * 1000 /* 5s */);
|
||||||
pollChannel.start();
|
$scope.pollChannel.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
var stopWatching = function() {
|
var stopWatching = function() {
|
||||||
if (pollChannel) {
|
if ($scope.pollChannel) {
|
||||||
pollChannel.stop();
|
$scope.pollChannel.stop();
|
||||||
pollChannel = null;
|
$scope.pollChannel = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
20
static/js/services/angular-poll-channel.js
vendored
20
static/js/services/angular-poll-channel.js
vendored
|
@ -1,8 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* Specialized class for conducting an HTTP poll, while properly preventing multiple calls.
|
* Specialized class for conducting an HTTP poll, while properly preventing multiple calls.
|
||||||
*/
|
*/
|
||||||
angular.module('quay').factory('AngularPollChannel', ['ApiService', '$timeout', 'DocumentVisibilityService',
|
angular.module('quay').factory('AngularPollChannel',
|
||||||
function(ApiService, $timeout, DocumentVisibilityService) {
|
['ApiService', '$timeout', 'DocumentVisibilityService', 'CORE_EVENT', '$rootScope',
|
||||||
|
function(ApiService, $timeout, DocumentVisibilityService, CORE_EVENT, $rootScope) {
|
||||||
var _PollChannel = function(scope, requester, opt_sleeptime) {
|
var _PollChannel = function(scope, requester, opt_sleeptime) {
|
||||||
this.scope_ = scope;
|
this.scope_ = scope;
|
||||||
this.requester_ = requester;
|
this.requester_ = requester;
|
||||||
|
@ -11,10 +12,20 @@ angular.module('quay').factory('AngularPollChannel', ['ApiService', '$timeout',
|
||||||
|
|
||||||
this.working = false;
|
this.working = false;
|
||||||
this.polling = false;
|
this.polling = false;
|
||||||
|
this.skipping = false;
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
|
var visibilityHandler = $rootScope.$on(CORE_EVENT.DOC_VISIBILITY_CHANGE, function() {
|
||||||
|
// If the poll channel was skipping because the visibility was hidden, call it immediately.
|
||||||
|
if (that.skipping && !DocumentVisibilityService.isHidden()) {
|
||||||
|
that.call_();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
scope.$on('$destroy', function() {
|
||||||
that.stop();
|
that.stop();
|
||||||
|
visibilityHandler();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,9 +39,10 @@ angular.module('quay').factory('AngularPollChannel', ['ApiService', '$timeout',
|
||||||
if (this.timer_) {
|
if (this.timer_) {
|
||||||
$timeout.cancel(this.timer_);
|
$timeout.cancel(this.timer_);
|
||||||
this.timer_ = null;
|
this.timer_ = null;
|
||||||
this.polling_ = false;
|
this.polling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.skipping = false;
|
||||||
this.working = false;
|
this.working = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +65,7 @@ angular.module('quay').factory('AngularPollChannel', ['ApiService', '$timeout',
|
||||||
|
|
||||||
// If the document is currently hidden, skip the call.
|
// If the document is currently hidden, skip the call.
|
||||||
if (DocumentVisibilityService.isHidden()) {
|
if (DocumentVisibilityService.isHidden()) {
|
||||||
|
this.skipping = true;
|
||||||
this.setupTimer_();
|
this.setupTimer_();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +76,7 @@ angular.module('quay').factory('AngularPollChannel', ['ApiService', '$timeout',
|
||||||
that.requester_(function(status) {
|
that.requester_(function(status) {
|
||||||
if (status) {
|
if (status) {
|
||||||
that.working = false;
|
that.working = false;
|
||||||
|
that.skipping = false;
|
||||||
that.setupTimer_();
|
that.setupTimer_();
|
||||||
} else {
|
} else {
|
||||||
that.stop();
|
that.stop();
|
||||||
|
|
Reference in a new issue