2015-05-07 21:55:40 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
define([
|
2015-06-14 15:24:03 +00:00
|
|
|
'underscore',
|
2015-05-07 21:55:40 +00:00
|
|
|
'react',
|
|
|
|
'reflux',
|
2015-05-10 16:53:33 +00:00
|
|
|
'app/stores/terminal',
|
2015-06-14 15:24:03 +00:00
|
|
|
'ansi_up',
|
2015-11-29 10:13:36 +00:00
|
|
|
'templates/app/components/terminal/terminal',
|
|
|
|
'templates/app/components/terminal/row'
|
|
|
|
], function(_, React, Reflux, terminalStore, ansiUp, template, rowTemplate) {
|
|
|
|
var TerminalRow = React.createClass({
|
|
|
|
render: rowTemplate,
|
|
|
|
shouldComponentUpdate: function(nextProps) {
|
|
|
|
return nextProps.row !== this.props.row;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
template = template.locals({
|
|
|
|
Row: TerminalRow
|
|
|
|
});
|
|
|
|
|
2015-05-07 21:55:40 +00:00
|
|
|
var Component = React.createClass({
|
|
|
|
mixins: [Reflux.ListenerMixin],
|
2015-12-02 21:27:09 +00:00
|
|
|
|
2015-11-18 20:14:46 +00:00
|
|
|
shouldScrollBottom: true,
|
2015-12-02 21:27:09 +00:00
|
|
|
data: [],
|
2015-11-29 20:29:39 +00:00
|
|
|
linesCount: 0,
|
2015-12-02 21:27:09 +00:00
|
|
|
|
2015-05-07 21:55:40 +00:00
|
|
|
componentDidMount: function() {
|
2015-05-10 16:53:33 +00:00
|
|
|
this.listenTo(terminalStore, this.updateItems);
|
2015-12-02 21:27:09 +00:00
|
|
|
var node = document.getElementsByClassName('terminal')[0];
|
2015-11-23 19:27:57 +00:00
|
|
|
this.initialScrollPosition = node.getBoundingClientRect().top;
|
2015-12-02 18:57:44 +00:00
|
|
|
|
2015-12-02 21:27:09 +00:00
|
|
|
$(window).on('scroll', this.onScroll);
|
|
|
|
},
|
|
|
|
componentWillUnmount: function() {
|
|
|
|
$(window).off('scroll', this.onScroll);
|
2015-05-07 21:55:40 +00:00
|
|
|
},
|
2015-11-29 20:29:39 +00:00
|
|
|
prepareRow: function(row) {
|
|
|
|
return ansiUp.ansi_to_html(row.replace('\r', ''));
|
|
|
|
},
|
2015-11-18 20:14:46 +00:00
|
|
|
prepareOutput: function(output) {
|
2015-11-29 20:29:39 +00:00
|
|
|
var self = this;
|
2015-11-18 20:14:46 +00:00
|
|
|
return output.map(function(row) {
|
2015-11-29 20:29:39 +00:00
|
|
|
return self.prepareRow(row);
|
2015-11-18 20:14:46 +00:00
|
|
|
});
|
2015-06-14 15:24:03 +00:00
|
|
|
},
|
2015-12-02 18:57:44 +00:00
|
|
|
onScroll: function() {
|
2015-12-02 21:27:09 +00:00
|
|
|
var node = document.getElementsByClassName('terminal')[0],
|
2015-11-23 19:27:57 +00:00
|
|
|
body = document.getElementsByTagName('body')[0];
|
|
|
|
this.shouldScrollBottom = window.innerHeight + body.scrollTop >=
|
|
|
|
node.offsetHeight + this.initialScrollPosition;
|
2015-06-14 15:24:03 +00:00
|
|
|
},
|
2015-12-02 18:57:44 +00:00
|
|
|
ensureScrollPosition: function() {
|
2015-11-18 20:14:46 +00:00
|
|
|
if (this.shouldScrollBottom) {
|
2015-12-02 21:27:09 +00:00
|
|
|
var node = document.getElementsByClassName('terminal')[0],
|
2015-11-23 19:27:57 +00:00
|
|
|
body = document.getElementsByTagName('body')[0];
|
|
|
|
body.scrollTop = this.initialScrollPosition + node.offsetHeight;
|
2015-11-18 20:14:46 +00:00
|
|
|
}
|
2015-07-08 20:37:31 +00:00
|
|
|
},
|
2015-11-29 20:29:39 +00:00
|
|
|
makeCodeLineContent: function(line) {
|
|
|
|
return '<span class="code-line_counter">' + '</span>' +
|
|
|
|
'<div class="code-line_body">' + this.prepareRow(line) + '</div>';
|
|
|
|
},
|
|
|
|
makeCodeLine: function(line, index) {
|
|
|
|
return '<div class="code-line" data-number="' + index + '">' +
|
|
|
|
this.makeCodeLineContent(line) + '</div>';
|
|
|
|
},
|
2015-12-02 18:57:44 +00:00
|
|
|
renderBuffer: _.throttle(function() {
|
|
|
|
var data = this.data,
|
|
|
|
currentLinesCount = data.length,
|
|
|
|
terminal = $('.terminal_code'),
|
|
|
|
rows = terminal.children();
|
2015-11-29 20:29:39 +00:00
|
|
|
|
2015-12-02 18:57:44 +00:00
|
|
|
if (rows.length) {
|
|
|
|
// replace our last node
|
|
|
|
var index = this.linesCount - 1;
|
|
|
|
$(rows[index]).html(this.makeCodeLineContent(data[index]));
|
|
|
|
}
|
2015-11-29 20:29:39 +00:00
|
|
|
|
2015-12-02 18:57:44 +00:00
|
|
|
var self = this;
|
|
|
|
terminal.append(
|
|
|
|
_(data.slice(this.linesCount)).map(function(line, index) {
|
|
|
|
return self.makeCodeLine(line, self.linesCount + index);
|
|
|
|
}).join('')
|
|
|
|
);
|
2015-11-29 20:29:39 +00:00
|
|
|
|
2015-12-02 18:57:44 +00:00
|
|
|
this.linesCount = currentLinesCount;
|
|
|
|
this.ensureScrollPosition();
|
|
|
|
}, 100),
|
|
|
|
updateItems: function(build) {
|
|
|
|
// listen just our console update
|
|
|
|
if (build.buildId === this.props.build) {
|
|
|
|
this.data = build.data;
|
|
|
|
this.renderBuffer();
|
2015-05-10 16:53:33 +00:00
|
|
|
}
|
2015-05-07 21:55:40 +00:00
|
|
|
},
|
2015-11-29 20:29:39 +00:00
|
|
|
shouldComponentUpdate: function() {
|
|
|
|
return false;
|
|
|
|
},
|
2015-05-17 13:48:16 +00:00
|
|
|
render: template,
|
2015-05-07 21:55:40 +00:00
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
2015-11-18 20:14:46 +00:00
|
|
|
data: []
|
2015-05-07 21:55:40 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return Component;
|
|
|
|
});
|