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')) { return logElement.empty(); } } }, createEngine(log) { var logElement; if (log || (log = this.get('log'))) { if (logElement = this.$('#log')) { logElement.empty(); } 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 event.preventDefault(); }, removeLogPopup() { if (this.get('canRemoveLog')) { this.get('popup').open('remove-log-popup'); return false; } } }, noop() {} });