
It turns out that jQuery's empty method can be really slow in Firefox, which can freeze the browser when cleaning the log.
228 lines
5.8 KiB
JavaScript
228 lines
5.8 KiB
JavaScript
import Ember from 'ember';
|
|
import LinesSelector from 'travis/utils/lines-selector';
|
|
import LogFolder from 'travis/utils/log-folder';
|
|
import config from 'travis/config/environment';
|
|
import { plainTextLog as plainTextLogUrl } from 'travis/utils/urls';
|
|
|
|
Log.DEBUG = false;
|
|
|
|
Log.LIMIT = 10000;
|
|
|
|
Log.Scroll = function(options) {
|
|
options = options || {};
|
|
this.beforeScroll = options.beforeScroll;
|
|
return this;
|
|
};
|
|
|
|
Log.Scroll.prototype = $.extend(new Log.Listener(), {
|
|
insert: function(log, data, pos) {
|
|
if (this.numbers) {
|
|
this.tryScroll();
|
|
}
|
|
return true;
|
|
},
|
|
tryScroll: function() {
|
|
var element, ref;
|
|
if (element = $("#log p:visible.highlight:first")) {
|
|
if (this.beforeScroll) {
|
|
this.beforeScroll();
|
|
}
|
|
$('#main').scrollTop(0);
|
|
return $('html, body').scrollTop(((ref = element.offset()) != null ? ref.top : void 0) - (window.innerHeight / 3));
|
|
}
|
|
}
|
|
});
|
|
|
|
Log.Limit = function(max_lines, limitedLogCallback) {
|
|
this.max_lines = max_lines || 1000;
|
|
this.limitedLogCallback = limitedLogCallback || (function() {});
|
|
return this;
|
|
};
|
|
|
|
Log.Limit.prototype = Log.extend(new Log.Listener(), {
|
|
count: 0,
|
|
insert: function(log, node, pos) {
|
|
if (node.type === 'paragraph' && !node.hidden) {
|
|
this.count += 1;
|
|
if (this.limited) {
|
|
this.limitedLogCallback();
|
|
}
|
|
return this.count;
|
|
}
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(Log.Limit.prototype, 'limited', {
|
|
get: function() {
|
|
return this.count >= this.max_lines;
|
|
}
|
|
});
|
|
|
|
export default Ember.Component.extend({
|
|
popup: Ember.inject.service(),
|
|
currentUserBinding: 'auth.currentUser',
|
|
|
|
didInsertElement() {
|
|
if (Log.DEBUG) {
|
|
console.log('log view: did insert');
|
|
}
|
|
this._super.apply(this, arguments);
|
|
return this.createEngine();
|
|
},
|
|
|
|
willDestroyElement() {
|
|
if (Log.DEBUG) {
|
|
console.log('log view: will destroy');
|
|
}
|
|
return this.teardownLog();
|
|
},
|
|
|
|
teardownLog(log) {
|
|
var logElement, parts, ref;
|
|
if (log || (log = this.get('log'))) {
|
|
parts = log.get('parts');
|
|
parts.removeArrayObserver(this, {
|
|
didChange: 'partsDidChange',
|
|
willChange: 'noop'
|
|
});
|
|
parts.destroy();
|
|
log.notifyPropertyChange('parts');
|
|
if ((ref = this.lineSelector) != null) {
|
|
ref.willDestroy();
|
|
}
|
|
if (logElement = this.$('#log')[0]) {
|
|
logElement.innerHTML = '';
|
|
}
|
|
}
|
|
},
|
|
|
|
createEngine(log) {
|
|
var logElement;
|
|
if (log || (log = this.get('log'))) {
|
|
if (logElement = this.$('#log')[0]) {
|
|
logElement.innerHTML = '';
|
|
}
|
|
log.onClear(() => {
|
|
this.teardownLog();
|
|
return this.createEngine();
|
|
});
|
|
this.scroll = new Log.Scroll({
|
|
beforeScroll: () => {
|
|
return this.unfoldHighlight();
|
|
}
|
|
});
|
|
this.limit = new Log.Limit(Log.LIMIT, () => {
|
|
return this.set('limited', true);
|
|
});
|
|
this.engine = Log.create({
|
|
listeners: [this.scroll, this.limit]
|
|
});
|
|
this.engine.limit = this.limit;
|
|
this.logFolder = new LogFolder(this.$('#log'));
|
|
this.lineSelector = new LinesSelector(this.$('#log'), this.scroll, this.logFolder);
|
|
return this.observeParts(log);
|
|
}
|
|
},
|
|
|
|
didUpdateAttrs(changes) {
|
|
this._super.apply(this, arguments);
|
|
if (!changes.oldAttrs) {
|
|
return;
|
|
}
|
|
if (changes.newAttrs.job.value && changes.oldAttrs.job.value && changes.newAttrs.job.value !== changes.oldAttrs.job.value) {
|
|
this.teardownLog(changes.oldAttrs.job.value.get('log'));
|
|
return this.createEngine(changes.newAttrs.job.value.get('log'));
|
|
}
|
|
},
|
|
|
|
unfoldHighlight() {
|
|
return this.lineSelector.unfoldLines();
|
|
},
|
|
|
|
observeParts(log) {
|
|
var parts;
|
|
if (log || (log = this.get('log'))) {
|
|
parts = log.get('parts');
|
|
parts.addArrayObserver(this, {
|
|
didChange: 'partsDidChange',
|
|
willChange: 'noop'
|
|
});
|
|
parts = parts.slice(0);
|
|
return this.partsDidChange(parts, 0, null, parts.length);
|
|
}
|
|
},
|
|
|
|
partsDidChange(parts, start, _, added) {
|
|
var i, j, len, part, ref, ref1, ref2, results;
|
|
if (Log.DEBUG) {
|
|
console.log('log view: parts did change');
|
|
}
|
|
if (this.get('state') !== 'inDOM') {
|
|
return;
|
|
}
|
|
ref = parts.slice(start, start + added);
|
|
results = [];
|
|
for (i = j = 0, len = ref.length; j < len; i = ++j) {
|
|
part = ref[i];
|
|
if ((ref1 = this.engine) != null ? (ref2 = ref1.limit) != null ? ref2.limited : void 0 : void 0) {
|
|
break;
|
|
}
|
|
results.push(this.engine.set(part.number, part.content));
|
|
}
|
|
return results;
|
|
},
|
|
|
|
plainTextLogUrl: function() {
|
|
var id, url;
|
|
if (id = this.get('log.job.id')) {
|
|
url = plainTextLogUrl(id);
|
|
if (config.pro) {
|
|
url += "&access_token=" + (this.get('job.log.token'));
|
|
}
|
|
return url;
|
|
}
|
|
}.property('job.log.id', 'job.log.token'),
|
|
|
|
hasPermission: function() {
|
|
var permissions;
|
|
if (permissions = this.get('currentUser.permissions')) {
|
|
return permissions.contains(parseInt(this.get('job.repo.id')));
|
|
}
|
|
}.property('currentUser.permissions.length', 'job.repo.id'),
|
|
|
|
canRemoveLog: function() {
|
|
var job;
|
|
if (job = this.get('job')) {
|
|
return job.get('canRemoveLog') && this.get('hasPermission');
|
|
}
|
|
}.property('job.canRemoveLog', 'hasPermission'),
|
|
|
|
showToTop: function() {
|
|
return this.get('log.hasContent') && this.get('job.canRemoveLog');
|
|
}.property('log.hasContent', 'job.canRemoveLog'),
|
|
|
|
showTailing: Ember.computed.alias('showToTop'),
|
|
|
|
actions: {
|
|
toTop() {
|
|
Travis.tailing.stop();
|
|
return $(window).scrollTop(0);
|
|
},
|
|
|
|
toggleTailing() {
|
|
Travis.tailing.toggle();
|
|
this.engine.autoCloseFold = !Travis.tailing.isActive();
|
|
return false;
|
|
},
|
|
|
|
removeLogPopup() {
|
|
if (this.get('canRemoveLog')) {
|
|
this.get('popup').open('remove-log-popup');
|
|
return false;
|
|
}
|
|
}
|
|
},
|
|
|
|
noop() {}
|
|
});
|