mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-02-11 10:19:15 +00:00
move to browserify
This commit is contained in:
parent
a042876009
commit
5879a7caf3
5
.jshintignore
Normal file
5
.jshintignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
static/scripts/**
|
||||||
|
static/js/**
|
||||||
|
node_modules/**
|
||||||
|
lib/node/jake/**
|
||||||
|
docs/build_docs/**
|
33
.jshintrc
Normal file
33
.jshintrc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"node": true,
|
||||||
|
"newcap": false,
|
||||||
|
"supernew": false,
|
||||||
|
"maxlen": 80,
|
||||||
|
"smarttabs": true,
|
||||||
|
"indent": 1,
|
||||||
|
"globalstrict": true,
|
||||||
|
"strict": true,
|
||||||
|
// use es3 to get 'extra comma' at object literal error
|
||||||
|
"es3": true,
|
||||||
|
// suppress warnings about switches with just one case
|
||||||
|
"onecase": true,
|
||||||
|
"nonew": false,
|
||||||
|
"trailing": true,
|
||||||
|
"sub": false,
|
||||||
|
"loopfunc": true,
|
||||||
|
"boss": false,
|
||||||
|
"lastsemic": false,
|
||||||
|
"quotmark": "single",
|
||||||
|
"undef": true,
|
||||||
|
"immed": true,
|
||||||
|
// allows ECMAScript 6 syntax (generators, etc)
|
||||||
|
"esnext": true,
|
||||||
|
// allow generators without a yield
|
||||||
|
"noyield": true,
|
||||||
|
"globals": {
|
||||||
|
"describe": false,
|
||||||
|
"it": false,
|
||||||
|
"before": false,
|
||||||
|
"after": false
|
||||||
|
}
|
||||||
|
}
|
10
app/actions/build.js
Normal file
10
app/actions/build.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Reflux = require('reflux');
|
||||||
|
|
||||||
|
module.exports = Reflux.createActions([
|
||||||
|
'cancel',
|
||||||
|
'readTerminalOutput',
|
||||||
|
'readAll',
|
||||||
|
'read'
|
||||||
|
]);
|
9
app/actions/buildLog.js
Normal file
9
app/actions/buildLog.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Reflux = require('reflux');
|
||||||
|
|
||||||
|
module.exports = Reflux.createActions([
|
||||||
|
'getTail',
|
||||||
|
'getLines'
|
||||||
|
]);
|
||||||
|
|
9
app/actions/project.js
Normal file
9
app/actions/project.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Reflux = require('reflux');
|
||||||
|
|
||||||
|
module.exports = Reflux.createActions([
|
||||||
|
'run',
|
||||||
|
'readAll',
|
||||||
|
'read'
|
||||||
|
]);
|
44
app/app.js
Normal file
44
app/app.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
ReactDOM = require('react-dom'),
|
||||||
|
App = require('./components/app'),
|
||||||
|
Dashboard = require('./components/dashboard'),
|
||||||
|
connect = require('./connect'),
|
||||||
|
resources = require('./resources'),
|
||||||
|
Router = require('react-router');
|
||||||
|
|
||||||
|
var Route = React.createFactory(Router.Route),
|
||||||
|
DefaultRoute = React.createFactory(Router.DefaultRoute);
|
||||||
|
|
||||||
|
var routes = (
|
||||||
|
Route({handler: App},
|
||||||
|
Route({
|
||||||
|
name: 'dashboard',
|
||||||
|
path: '/',
|
||||||
|
handler: Dashboard
|
||||||
|
})
|
||||||
|
//Route({
|
||||||
|
//name: 'project',
|
||||||
|
//path: 'projects/:name',
|
||||||
|
//handler: Components.Project.View
|
||||||
|
//}),
|
||||||
|
//Route({name: 'build', path: 'builds/:id', handler: Components.Build.View}),
|
||||||
|
//Route({
|
||||||
|
//name: 'buildLog',
|
||||||
|
//path: 'builds/:buildId/log',
|
||||||
|
//handler: Components.BuildLog
|
||||||
|
//})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
connect.io.on('connect', function() {
|
||||||
|
console.log('on connect');
|
||||||
|
Router.run(routes, Router.HistoryLocation, function(Handler) {
|
||||||
|
ReactDOM.render(
|
||||||
|
React.createElement(Handler),
|
||||||
|
document.getElementById('content')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
5
app/components/app/index.jade
Normal file
5
app/components/app/index.jade
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
div
|
||||||
|
Header()
|
||||||
|
.container-fluid
|
||||||
|
.page-wrapper
|
||||||
|
RouteHandler()
|
23
app/components/app/index.js
Normal file
23
app/components/app/index.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
Router = require('react-router'),
|
||||||
|
Header = require('../header'),
|
||||||
|
ProjectActions = require('../../actions/project'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
componentDidMount: function() {
|
||||||
|
console.log('read all projects in component');
|
||||||
|
ProjectActions.readAll();
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return template({
|
||||||
|
Link: Router.Link,
|
||||||
|
Header: Header,
|
||||||
|
RouteHandler: Router.RouteHandler
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
94
app/components/builds/item/index.jade
Normal file
94
app/components/builds/item/index.jade
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
mixin statusText(build)
|
||||||
|
if build.status === 'in-progress'
|
||||||
|
span in progress
|
||||||
|
|
||||||
|
if build.status === 'queued'
|
||||||
|
span queued
|
||||||
|
|
||||||
|
if build.status === 'done'
|
||||||
|
span done
|
||||||
|
|
||||||
|
if build.status === 'error'
|
||||||
|
span error
|
||||||
|
|
||||||
|
- var build = this.props.build;
|
||||||
|
|
||||||
|
.build(class="")
|
||||||
|
.build_content
|
||||||
|
.build_status
|
||||||
|
.status(class="status__#{build.status}")
|
||||||
|
div.build_header
|
||||||
|
if build.project
|
||||||
|
span
|
||||||
|
Scm(scm=build.project.scm.type)
|
||||||
|
|
|
||||||
|
Link(to="project", params={name: build.project.name})
|
||||||
|
span= build.project.name
|
||||||
|
|
|
||||||
|
if build.number
|
||||||
|
span(style={fontSize: '15px', color: '#a6a6a6'}) build
|
||||||
|
|
|
||||||
|
if build.status !== 'queued'
|
||||||
|
Link(to="build", params={id: build.id})
|
||||||
|
span #
|
||||||
|
span= build.number
|
||||||
|
else
|
||||||
|
span #
|
||||||
|
span= build.number
|
||||||
|
|
||||||
|
if build.waitReason
|
||||||
|
span (
|
||||||
|
span= build.waitReason
|
||||||
|
span , waiting)
|
||||||
|
|
||||||
|
if build.status === 'in-progress' && build.currentStep
|
||||||
|
span (
|
||||||
|
span= build.currentStep
|
||||||
|
span )
|
||||||
|
|
||||||
|
div
|
||||||
|
if build.endDate
|
||||||
|
span.build_info
|
||||||
|
i.fa.fa-fw.fa-clock-o
|
||||||
|
| finished
|
||||||
|
DateTime(value=build.endDate)
|
||||||
|
|
|
||||||
|
Duration(value=(build.endDate - build.startDate), withSuffix=true)
|
||||||
|
else
|
||||||
|
if build.startDate
|
||||||
|
span.build_info
|
||||||
|
i.fa.fa-fw.fa-clock-o
|
||||||
|
| started
|
||||||
|
DateTime(value=build.startDate)
|
||||||
|
else
|
||||||
|
span.build_info
|
||||||
|
i.fa.fa-fw.fa-clock-o
|
||||||
|
| queued
|
||||||
|
DateTime(value=build.createDate)
|
||||||
|
|
|
||||||
|
if build.scm
|
||||||
|
span.build_info
|
||||||
|
i.fa.fa-fw.fa-comment-o
|
||||||
|
|
|
||||||
|
span= utils.prune(build.scm.rev.comment, 40)
|
||||||
|
|
|
||||||
|
|
||||||
|
.build_controls
|
||||||
|
if build.completed
|
||||||
|
.build_controls_buttons
|
||||||
|
a.btn.btn-sm.btn-default(href="javascript:void(0);", onClick=this.onRebuildProject(build.project.name))
|
||||||
|
i.fa.fa-fw.fa-repeat(title="Rebuild")
|
||||||
|
|
|
||||||
|
| Build again
|
||||||
|
if build.status === 'in-progress'
|
||||||
|
.build_controls_progress
|
||||||
|
if build.project.avgBuildDuration
|
||||||
|
Progress(build=build)
|
||||||
|
if build.status === 'queued'
|
||||||
|
.build_controls_buttons
|
||||||
|
a.btn.btn-sm.btn-default(href="javascript:void(0);", onClick=this.onCancelBuild(build.id))
|
||||||
|
i.fa.fa-fw.fa-times(title="Cancel build")
|
||||||
|
|
|
||||||
|
| Cancel build
|
||||||
|
|
||||||
|
|
25
app/components/builds/item/index.js
Normal file
25
app/components/builds/item/index.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
React = require('react'),
|
||||||
|
Router = require('react-router'),
|
||||||
|
ProjectActions = require('../../../actions/project'),
|
||||||
|
BuildActions = require('../../../actions/build'),
|
||||||
|
CommonComponents = require('../../common'),
|
||||||
|
utils = require('../../../utils'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
onRebuildProject: function(projectName) {
|
||||||
|
ProjectActions.run(projectName);
|
||||||
|
},
|
||||||
|
onCancelBuild: function(buildId) {
|
||||||
|
BuildActions.cancel(buildId);
|
||||||
|
},
|
||||||
|
render: template.locals(_({
|
||||||
|
Link: Router.Link,
|
||||||
|
utils: utils
|
||||||
|
}).extend(CommonComponents))
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
7
app/components/builds/list/index.jade
Normal file
7
app/components/builds/list/index.jade
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.builds
|
||||||
|
if !this.state.items.length
|
||||||
|
p Build history is empty
|
||||||
|
- console.log('>>>> builds = ', JSON.stringify(this.state.items).length, this.state.items)
|
||||||
|
each build, index in this.state.items
|
||||||
|
Item(build=build, key=build.id)
|
||||||
|
|
28
app/components/builds/list/index.js
Normal file
28
app/components/builds/list/index.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
React = require('react'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
Item = require('../item'),
|
||||||
|
buildsStore = require('../../../stores/builds'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
mixins: [
|
||||||
|
Reflux.connectFilter(buildsStore, 'items', function(items) {
|
||||||
|
var projectName = this.props.projectName;
|
||||||
|
if (projectName) {
|
||||||
|
return _(items).filter(function(item) {
|
||||||
|
return item.project && item.project.name === projectName;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
render: template.locals({
|
||||||
|
Item: Item
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
13
app/components/common/dateTime/index.js
Normal file
13
app/components/common/dateTime/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
template = require('./template.jade'),
|
||||||
|
moment = require('moment');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
render: template.locals({
|
||||||
|
moment: moment
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
13
app/components/common/duration/index.js
Normal file
13
app/components/common/duration/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
template = require('./index.jade'),
|
||||||
|
moment = require('moment');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
render: template.locals({
|
||||||
|
moment: moment
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
13
app/components/common/index.js
Normal file
13
app/components/common/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var DateTime = require('./dateTime'),
|
||||||
|
Duration = require('./duration'),
|
||||||
|
Progress = require('./progress'),
|
||||||
|
Scm = require('./scm');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
DateTime: DateTime,
|
||||||
|
Scm: Scm,
|
||||||
|
Duration: Duration,
|
||||||
|
Progress: Progress
|
||||||
|
};
|
32
app/components/common/progress/index.js
Normal file
32
app/components/common/progress/index.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
_ = require('underscore'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
render: template,
|
||||||
|
_computePercent: function() {
|
||||||
|
var build = this.props.build;
|
||||||
|
return Math.round((Date.now() - build.startDate) /
|
||||||
|
build.project.avgBuildDuration * 100);
|
||||||
|
},
|
||||||
|
componentDidMount: function() {
|
||||||
|
var self = this;
|
||||||
|
var updateCallback = function() {
|
||||||
|
if (self.props.build.status === 'in-progress') {
|
||||||
|
if (self.isMounted()) {
|
||||||
|
self.setState({percent: self._computePercent()});
|
||||||
|
_.delay(updateCallback, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateCallback();
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
percent: this._computePercent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
9
app/components/common/scm/index.js
Normal file
9
app/components/common/scm/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
render: template
|
||||||
|
});
|
||||||
|
|
5
app/components/dashboard/index.jade
Normal file
5
app/components/dashboard/index.jade
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.main-row
|
||||||
|
.row
|
||||||
|
.col-md-8.col-sm-12
|
||||||
|
h2 Builds history
|
||||||
|
BuildsList()
|
19
app/components/dashboard/index.js
Normal file
19
app/components/dashboard/index.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
Router = require('react-router'),
|
||||||
|
ProjectActions = require('../../actions/project'),
|
||||||
|
BuildActions = require('../../actions/build'),
|
||||||
|
BuildsList = require('../builds/list'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
componentWillMount: function() {
|
||||||
|
ProjectActions.readAll();
|
||||||
|
BuildActions.readAll();
|
||||||
|
},
|
||||||
|
render: template.locals({
|
||||||
|
Link: Router.Link,
|
||||||
|
BuildsList: BuildsList
|
||||||
|
})
|
||||||
|
});
|
15
app/components/header/index.js
Normal file
15
app/components/header/index.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
Router = require('react-router'),
|
||||||
|
ProjectsSelector = require('../projects-selector'),
|
||||||
|
template = require('./index.jade');
|
||||||
|
|
||||||
|
var Component = React.createClass({
|
||||||
|
render: template.locals({
|
||||||
|
Link: Router.Link,
|
||||||
|
ProjectsSelector: ProjectsSelector
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Component;
|
24
app/components/projects-selector/index.jade
Normal file
24
app/components/projects-selector/index.jade
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
.projects-selector(href="javascript:void(0);")
|
||||||
|
if !this.state.showSearch
|
||||||
|
span.projects-selector_preview(onClick=this.onSearchProject)
|
||||||
|
i.fa.fa-fw.fa-bars
|
||||||
|
span.projects-selector_preview_text Select a project...
|
||||||
|
else
|
||||||
|
input.projects-selector_input(
|
||||||
|
type="text",
|
||||||
|
value=this.state.searchQuery,
|
||||||
|
onChange=this.onSearchChange,
|
||||||
|
ref=this.onInputMount,
|
||||||
|
onBlur=this.onBlurSearch
|
||||||
|
)
|
||||||
|
ul.projects-selector_items
|
||||||
|
each project in this.state.projects
|
||||||
|
li.projects-selector_item(key=project.name)
|
||||||
|
Link.projects-selector_item_link(to="project", params={name: project.name}, onMouseDown=this.onSelectProject(project.name))
|
||||||
|
Scm(scm=project.scm.type)
|
||||||
|
span
|
||||||
|
span= project.name
|
||||||
|
a.projects-selector_item_run(href="javascript:void(0);", onMouseDown=this.onRunProject(project.name))
|
||||||
|
i.fa.fa-fw.fa-play
|
||||||
|
|
||||||
|
|
54
app/components/projects-selector/index.js
Normal file
54
app/components/projects-selector/index.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react'),
|
||||||
|
ReactDOM = require('react-dom'),
|
||||||
|
Router = require('react-router'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
ProjectActions = require('../../actions/project'),
|
||||||
|
projectsStore = require('../../stores/project'),
|
||||||
|
template = require('./index.jade'),
|
||||||
|
Scm = require('../common/scm');
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
mixins: [Reflux.ListenerMixin, Router.Navigation],
|
||||||
|
componentDidMount: function() {
|
||||||
|
this.listenTo(projectsStore, this.updateItems);
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
showSearch: false,
|
||||||
|
projects: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onRunProject: function(projectName) {
|
||||||
|
ProjectActions.run(projectName);
|
||||||
|
this.setState({showSearch: false});
|
||||||
|
},
|
||||||
|
onSelectProject: function(name) {
|
||||||
|
this.transitionTo('project', {name: name});
|
||||||
|
},
|
||||||
|
updateItems: function(projects) {
|
||||||
|
this.setState({projects: projects});
|
||||||
|
},
|
||||||
|
onSearchProject: function() {
|
||||||
|
this.setState({showSearch: true});
|
||||||
|
},
|
||||||
|
onInputMount: function(component) {
|
||||||
|
var node = ReactDOM.findDOMNode(component);
|
||||||
|
if (node) {
|
||||||
|
node.focus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onBlurSearch: function() {
|
||||||
|
this.setState({showSearch: false});
|
||||||
|
},
|
||||||
|
onSearchChange: function(event) {
|
||||||
|
var query = event.target.value;
|
||||||
|
this.setState({searchQuery: query});
|
||||||
|
ProjectActions.readAll({nameQuery: query});
|
||||||
|
},
|
||||||
|
render: template.locals({
|
||||||
|
Link: Router.Link,
|
||||||
|
Scm: Scm
|
||||||
|
})
|
||||||
|
});
|
9
app/connect.js
Normal file
9
app/connect.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var socketio = require('socket.io-client'),
|
||||||
|
dataio = require('data.io/data.io'),
|
||||||
|
io = socketio(),
|
||||||
|
data = dataio(io);
|
||||||
|
|
||||||
|
module.exports.io = io;
|
||||||
|
module.exports.data = data;
|
10
app/resources.js
Normal file
10
app/resources.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var connect = require('./connect'),
|
||||||
|
projects = connect.data.resource('projects'),
|
||||||
|
builds = connect.data.resource('builds');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
projects: projects,
|
||||||
|
builds: builds
|
||||||
|
};
|
34
app/stores/build.js
Normal file
34
app/stores/build.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
BuildActions = require('../actions/build'),
|
||||||
|
resources = require('../resources'),
|
||||||
|
resource = resources.builds;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildActions,
|
||||||
|
build: null,
|
||||||
|
|
||||||
|
onChange: function(data, action) {
|
||||||
|
if (this.build && (data.buildId === this.build.id)) {
|
||||||
|
_(this.build).extend(data.changes);
|
||||||
|
this.trigger(this.build);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
resource.subscribe('change', this.onChange);
|
||||||
|
},
|
||||||
|
|
||||||
|
onRead: function(id) {
|
||||||
|
var self = this;
|
||||||
|
resource.sync('read', {id: id}, function(err, build) {
|
||||||
|
if (err) throw err;
|
||||||
|
self.build = build;
|
||||||
|
self.trigger(self.build);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
43
app/stores/buildLog.js
Normal file
43
app/stores/buildLog.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Reflux = require('reflux'),
|
||||||
|
BuildLogActions = require('../actions/buildLog'),
|
||||||
|
resources = require('../resources'),
|
||||||
|
resource = resources.builds;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildLogActions,
|
||||||
|
data: {
|
||||||
|
lines: [],
|
||||||
|
total: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return this.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
onGetTail: function(params) {
|
||||||
|
var self = this;
|
||||||
|
console.time('>>> getBuildLogTail');
|
||||||
|
resource.sync('getBuildLogTail', params, function(err, data) {
|
||||||
|
if (err) throw err;
|
||||||
|
console.timeEnd('>>> getBuildLogTail');
|
||||||
|
self.data = data;
|
||||||
|
self.trigger(self.data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onGetLines: function(params) {
|
||||||
|
var self = this;
|
||||||
|
console.time('>>> getBuildLogLines');
|
||||||
|
resource.sync('getBuildLogLines', params, function(err, data) {
|
||||||
|
if (err) throw err;
|
||||||
|
console.timeEnd('>>> getBuildLogLines');
|
||||||
|
console.log('>>> isLast log lines = ', data.isLast);
|
||||||
|
self.data.lines = data.lines;
|
||||||
|
self.trigger(self.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
66
app/stores/builds.js
Normal file
66
app/stores/builds.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
BuildActions = require('../actions/build'),
|
||||||
|
resources = require('../resources'),
|
||||||
|
resource = resources.builds;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildActions,
|
||||||
|
builds: [],
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return this.builds;
|
||||||
|
},
|
||||||
|
|
||||||
|
onChanged: function(data) {
|
||||||
|
var oldBuild = _(this.builds).findWhere({id: data.buildId});
|
||||||
|
if (oldBuild) {
|
||||||
|
_(oldBuild).extend(data.changes);
|
||||||
|
} else {
|
||||||
|
this.builds.unshift(
|
||||||
|
_({id: data.buildId}).extend(data.changes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger(this.builds);
|
||||||
|
},
|
||||||
|
|
||||||
|
onCancelled: function(data) {
|
||||||
|
// WORKAROUND: client that trigger `onCancel` gets one `onCancelled`
|
||||||
|
// call other clients get 2 calls (second with empty data)
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var index = _(this.builds).findIndex({id: data.buildId});
|
||||||
|
if (index !== -1) {
|
||||||
|
this.builds.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger(this.builds);
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
resource.subscribe('change', this.onChanged);
|
||||||
|
resource.subscribe('cancel', this.onCancelled);
|
||||||
|
},
|
||||||
|
|
||||||
|
onReadAll: function(params) {
|
||||||
|
var self = this;
|
||||||
|
resource.sync('readAll', params, function(err, builds) {
|
||||||
|
if (err) throw err;
|
||||||
|
self.builds = builds;
|
||||||
|
self.trigger(self.builds);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onCancel: function(buildId) {
|
||||||
|
resource.sync('cancel', {buildId: buildId}, function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
||||||
|
|
35
app/stores/project.js
Normal file
35
app/stores/project.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
ProjectActions = require('../actions/project'),
|
||||||
|
resources = require('../resources'),
|
||||||
|
resource = resources.projects;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: ProjectActions,
|
||||||
|
project: {},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return this.project;
|
||||||
|
},
|
||||||
|
|
||||||
|
onChange: function(data, action) {
|
||||||
|
this.trigger(data.project);
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
resource.subscribe('change', this.onChange);
|
||||||
|
},
|
||||||
|
|
||||||
|
onRead: function(params) {
|
||||||
|
var self = this;
|
||||||
|
resource.sync('read', params, function(err, project) {
|
||||||
|
if (err) throw err;
|
||||||
|
self.project = project;
|
||||||
|
self.trigger(self.project);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
23
app/stores/projects.js
Normal file
23
app/stores/projects.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Reflux = require('reflux'),
|
||||||
|
ProjectActions = require('../actions/project'),
|
||||||
|
resource = require('../resources').projects;
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: ProjectActions,
|
||||||
|
onRun: function(projectName) {
|
||||||
|
resource.sync('run', {projectName: projectName}, function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onReadAll: function(params) {
|
||||||
|
var self = this;
|
||||||
|
resource.sync('readAll', params, function(err, projects) {
|
||||||
|
if (err) throw err;
|
||||||
|
self.trigger(projects);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
64
app/stores/terminal.js
Normal file
64
app/stores/terminal.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
Reflux = require('reflux'),
|
||||||
|
BuildActions = require('../actions/build'),
|
||||||
|
connect = require('app/connect');
|
||||||
|
|
||||||
|
var Store = Reflux.createStore({
|
||||||
|
listenables: BuildActions,
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
// the only purpose of this hash to reconnect all the time
|
||||||
|
// except first, see notes at using
|
||||||
|
this.connectedResourcesHash = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
onReadTerminalOutput: function(build) {
|
||||||
|
var self = this,
|
||||||
|
output = [],
|
||||||
|
resourceName = 'build' + build.id;
|
||||||
|
|
||||||
|
var connectToBuildDataResource = function() {
|
||||||
|
// reconnect for get data below (at subscribe), coz
|
||||||
|
// data emitted only once during connect
|
||||||
|
if (self.connectedResourcesHash[resourceName]) {
|
||||||
|
connect.resource(resourceName).reconnect();
|
||||||
|
} else {
|
||||||
|
self.connectedResourcesHash[resourceName] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect.resource(resourceName).subscribe('data', function(data) {
|
||||||
|
var lastLine = _(self.lines).last();
|
||||||
|
if (lastLine && (_(data.lines).first().number === lastLine.number)) {
|
||||||
|
self.lines = _(self.lines).initial();
|
||||||
|
}
|
||||||
|
self.lines = self.lines.concat(data.lines);
|
||||||
|
self.trigger({
|
||||||
|
buildId: build.id,
|
||||||
|
name: 'Console for build #' + build.id,
|
||||||
|
data: _(self.lines).pluck('text')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.lines = [];
|
||||||
|
this.currentLine = '';
|
||||||
|
|
||||||
|
// create data resource for completed build
|
||||||
|
if (build.completed) {
|
||||||
|
connect.resource('projects').sync(
|
||||||
|
'createBuildDataResource',
|
||||||
|
{buildId: build.id},
|
||||||
|
function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
connectToBuildDataResource();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
connectToBuildDataResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Store;
|
16
app/utils.js
Normal file
16
app/utils.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var utils = {};
|
||||||
|
|
||||||
|
utils.prune = function(str, length) {
|
||||||
|
var result = '',
|
||||||
|
words = str.split(' ');
|
||||||
|
|
||||||
|
do {
|
||||||
|
result += words.shift() + ' ';
|
||||||
|
} while (words.length && result.length < length);
|
||||||
|
|
||||||
|
return result.replace(/ $/, words.length ? '...' : '');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = utils;
|
12
package.json
12
package.json
@ -8,7 +8,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"makeTestRepos": "rm -rf test/repos/{mercurial,git}; cd test/repos/ && tar -xf mercurial.tar.gz && tar -xf git.tar.gz",
|
"makeTestRepos": "rm -rf test/repos/{mercurial,git}; cd test/repos/ && tar -xf mercurial.tar.gz && tar -xf git.tar.gz",
|
||||||
"test": "npm run makeTestRepos && mocha --bail --reporter=spec --timeout 4000",
|
"test": "npm run makeTestRepos && mocha --bail --reporter=spec --timeout 4000",
|
||||||
"dev": "gulp",
|
"watchLess": "catw -c 'lessc static/css/index.less' 'static/css/**/*.less' > static/css/index.css",
|
||||||
|
"watchJs": "watchify app/app.js -t react-jade -o static/js/app.build.js -dv",
|
||||||
|
"dev": "npm run watchJs & nodemon app.js",
|
||||||
"sync": "npm install && npm prune && bower install && bower prune",
|
"sync": "npm install && npm prune && bower install && bower prune",
|
||||||
"buildJs": "r.js -o static/js/requirejs/buid.js",
|
"buildJs": "r.js -o static/js/requirejs/buid.js",
|
||||||
"buildClean": "rm static/index.html",
|
"buildClean": "rm static/index.html",
|
||||||
@ -46,20 +48,22 @@
|
|||||||
"colors": "1.1.2",
|
"colors": "1.1.2",
|
||||||
"cron": "1.0.9",
|
"cron": "1.0.9",
|
||||||
"data.io": "0.3.0",
|
"data.io": "0.3.0",
|
||||||
|
"moment": "^2.10.6",
|
||||||
"nlevel": "1.0.3",
|
"nlevel": "1.0.3",
|
||||||
"node-static": "0.7.6",
|
"node-static": "0.7.6",
|
||||||
"socket.io": "1.3.5",
|
"socket.io": "1.3.5",
|
||||||
|
"socket.io-client": "^1.3.7",
|
||||||
|
"through": "2.3.6",
|
||||||
"twostep": "0.4.1",
|
"twostep": "0.4.1",
|
||||||
"underscore": "1.8.3",
|
"underscore": "1.8.3"
|
||||||
"through": "2.3.6"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bower": "1.4.1",
|
"bower": "1.4.1",
|
||||||
|
"catw": "^1.0.1",
|
||||||
"expect.js": "0.3.1",
|
"expect.js": "0.3.1",
|
||||||
"gulp": "3.8.11",
|
"gulp": "3.8.11",
|
||||||
"gulp-less": "3.0.3",
|
"gulp-less": "3.0.3",
|
||||||
"gulp-nodemon": "2.0.3",
|
"gulp-nodemon": "2.0.3",
|
||||||
"gulp-react-jade-amd": "git://github.com/vladimir-polyakov/gulp-react-jade-amd",
|
|
||||||
"jade": "1.11.0",
|
"jade": "1.11.0",
|
||||||
"main-bower-files": "2.7.0",
|
"main-bower-files": "2.7.0",
|
||||||
"memdown": "1.1.0",
|
"memdown": "1.1.0",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,700&subset=latin,cyrillic-ext);
|
/*@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,700&subset=latin,cyrillic-ext);*/
|
||||||
|
|
||||||
@bowerPath: "../js/libs";
|
@bowerPath: "../js/libs";
|
||||||
|
|
||||||
@ -24,3 +24,4 @@
|
|||||||
@import "./sources/components/builds.less";
|
@import "./sources/components/builds.less";
|
||||||
@import "./sources/components/projects.less";
|
@import "./sources/components/projects.less";
|
||||||
@import "./sources/components/terminal.less";
|
@import "./sources/components/terminal.less";
|
||||||
|
|
||||||
|
36401
static/js/app.build.js
36401
static/js/app.build.js
File diff suppressed because one or more lines are too long
@ -1,12 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define(['reflux'], function(Reflux) {
|
|
||||||
var Actions = Reflux.createActions([
|
|
||||||
'cancel',
|
|
||||||
'readTerminalOutput',
|
|
||||||
'readAll',
|
|
||||||
'read'
|
|
||||||
]);
|
|
||||||
|
|
||||||
return Actions;
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define(['reflux'], function(Reflux) {
|
|
||||||
var Actions = Reflux.createActions([
|
|
||||||
'getTail',
|
|
||||||
'getLines'
|
|
||||||
]);
|
|
||||||
|
|
||||||
return Actions;
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define(['reflux'], function(Reflux) {
|
|
||||||
var Actions = Reflux.createActions([
|
|
||||||
'run',
|
|
||||||
'readAll',
|
|
||||||
'read'
|
|
||||||
]);
|
|
||||||
|
|
||||||
return Actions;
|
|
||||||
});
|
|
@ -1,17 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'react',
|
|
||||||
'templates/app/components/common/dateTime/template',
|
|
||||||
'moment'
|
|
||||||
], function(React, template, moment) {
|
|
||||||
template = template.locals({
|
|
||||||
moment: moment
|
|
||||||
});
|
|
||||||
|
|
||||||
var Component = React.createClass({
|
|
||||||
render: template
|
|
||||||
});
|
|
||||||
|
|
||||||
return Component;
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'react', 'templates/app/components/common/duration/index', 'moment'
|
|
||||||
], function(React, template, moment) {
|
|
||||||
template = template.locals({
|
|
||||||
moment: moment
|
|
||||||
});
|
|
||||||
|
|
||||||
var Component = React.createClass({
|
|
||||||
render: template
|
|
||||||
});
|
|
||||||
|
|
||||||
return Component;
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'./dateTime/index',
|
|
||||||
'./scm/index',
|
|
||||||
'./duration/index',
|
|
||||||
'./progress/index'
|
|
||||||
], function(DateTime, Scm, Duration, Progress) {
|
|
||||||
return {
|
|
||||||
DateTime: DateTime,
|
|
||||||
Scm: Scm,
|
|
||||||
Duration: Duration,
|
|
||||||
Progress: Progress
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,34 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'underscore',
|
|
||||||
'react',
|
|
||||||
'templates/app/components/common/progress/index'
|
|
||||||
], function(_, React, template) {
|
|
||||||
return React.createClass({
|
|
||||||
render: template,
|
|
||||||
_computePercent: function() {
|
|
||||||
var build = this.props.build;
|
|
||||||
return Math.round((Date.now() - build.startDate) /
|
|
||||||
build.project.avgBuildDuration * 100);
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
var self = this;
|
|
||||||
var updateCallback = function() {
|
|
||||||
if (self.props.build.status === 'in-progress') {
|
|
||||||
if (self.isMounted()) {
|
|
||||||
self.setState({percent: self._computePercent()});
|
|
||||||
_.delay(updateCallback, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateCallback();
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
percent: this._computePercent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'react', 'templates/app/components/common/scm/index'
|
|
||||||
], function(React, template) {
|
|
||||||
return React.createClass({
|
|
||||||
render: template
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'react',
|
|
||||||
'react-router',
|
|
||||||
'app/components/projects/selector/index',
|
|
||||||
'templates/app/components/header/index',
|
|
||||||
'bootstrap/collapse'
|
|
||||||
], function(React, Router, ProjectsSelector, template) {
|
|
||||||
template = template.locals({
|
|
||||||
Link: Router.Link,
|
|
||||||
ProjectsSelector: ProjectsSelector
|
|
||||||
});
|
|
||||||
|
|
||||||
var Component = React.createClass({
|
|
||||||
render: template
|
|
||||||
});
|
|
||||||
|
|
||||||
return Component;
|
|
||||||
});
|
|
@ -1,8 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'socketio', 'dataio'
|
|
||||||
], function(socketio, dataio) {
|
|
||||||
// Do it because we use connect in console store
|
|
||||||
return dataio(socketio.connect());
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define(['app/connect'], function(connect) {
|
|
||||||
var projects = connect.resource('projects');
|
|
||||||
var builds = connect.resource('builds');
|
|
||||||
|
|
||||||
return {
|
|
||||||
projects: projects,
|
|
||||||
builds: builds
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,35 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'underscore',
|
|
||||||
'reflux', 'app/actions/build', 'app/resources'
|
|
||||||
], function(_, Reflux, BuildActions, resources) {
|
|
||||||
var resource = resources.builds;
|
|
||||||
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: BuildActions,
|
|
||||||
build: null,
|
|
||||||
|
|
||||||
onChange: function(data, action) {
|
|
||||||
if (this.build && (data.buildId === this.build.id)) {
|
|
||||||
_(this.build).extend(data.changes);
|
|
||||||
this.trigger(this.build);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
resource.subscribe('change', this.onChange);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRead: function(id) {
|
|
||||||
var self = this;
|
|
||||||
resource.sync('read', {id: id}, function(err, build) {
|
|
||||||
if (err) throw err;
|
|
||||||
self.build = build;
|
|
||||||
self.trigger(self.build);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,46 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'reflux', 'app/actions/buildLog', 'app/resources'
|
|
||||||
], function(
|
|
||||||
Reflux, BuildLogActions, resources
|
|
||||||
) {
|
|
||||||
var resource = resources.builds;
|
|
||||||
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: BuildLogActions,
|
|
||||||
data: {
|
|
||||||
lines: [],
|
|
||||||
total: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return this.data;
|
|
||||||
},
|
|
||||||
|
|
||||||
onGetTail: function(params) {
|
|
||||||
var self = this;
|
|
||||||
console.time('>>> getBuildLogTail');
|
|
||||||
resource.sync('getBuildLogTail', params, function(err, data) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.timeEnd('>>> getBuildLogTail');
|
|
||||||
self.data = data;
|
|
||||||
self.trigger(self.data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onGetLines: function(params) {
|
|
||||||
var self = this;
|
|
||||||
console.time('>>> getBuildLogLines');
|
|
||||||
resource.sync('getBuildLogLines', params, function(err, data) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.timeEnd('>>> getBuildLogLines');
|
|
||||||
console.log('>>> isLast log lines = ', data.isLast);
|
|
||||||
self.data.lines = data.lines;
|
|
||||||
self.trigger(self.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,66 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'underscore',
|
|
||||||
'reflux', 'app/actions/build', 'app/resources'
|
|
||||||
], function(_, Reflux, BuildActions, resources) {
|
|
||||||
var resource = resources.builds;
|
|
||||||
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: BuildActions,
|
|
||||||
builds: [],
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return this.builds;
|
|
||||||
},
|
|
||||||
|
|
||||||
onChanged: function(data) {
|
|
||||||
var oldBuild = _(this.builds).findWhere({id: data.buildId});
|
|
||||||
if (oldBuild) {
|
|
||||||
_(oldBuild).extend(data.changes);
|
|
||||||
} else {
|
|
||||||
this.builds.unshift(
|
|
||||||
_({id: data.buildId}).extend(data.changes)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.trigger(this.builds);
|
|
||||||
},
|
|
||||||
|
|
||||||
onCancelled: function(data) {
|
|
||||||
// WORKAROUND: client that trigger `onCancel` gets one `onCancelled`
|
|
||||||
// call other clients get 2 calls (second with empty data)
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var index = _(this.builds).findIndex({id: data.buildId});
|
|
||||||
if (index !== -1) {
|
|
||||||
this.builds.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.trigger(this.builds);
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
resource.subscribe('change', this.onChanged);
|
|
||||||
resource.subscribe('cancel', this.onCancelled);
|
|
||||||
},
|
|
||||||
|
|
||||||
onReadAll: function(params) {
|
|
||||||
var self = this;
|
|
||||||
resource.sync('readAll', params, function(err, builds) {
|
|
||||||
if (err) throw err;
|
|
||||||
self.builds = builds;
|
|
||||||
self.trigger(self.builds);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onCancel: function(buildId) {
|
|
||||||
resource.sync('cancel', {buildId: buildId}, function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,36 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'underscore',
|
|
||||||
'reflux', 'app/actions/project', 'app/resources'
|
|
||||||
], function(_, Reflux, ProjectActions, resources) {
|
|
||||||
var resource = resources.projects;
|
|
||||||
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: ProjectActions,
|
|
||||||
project: {},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return this.project;
|
|
||||||
},
|
|
||||||
|
|
||||||
onChange: function(data, action) {
|
|
||||||
this.trigger(data.project);
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
resource.subscribe('change', this.onChange);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRead: function(params) {
|
|
||||||
var self = this;
|
|
||||||
resource.sync('read', params, function(err, project) {
|
|
||||||
if (err) throw err;
|
|
||||||
self.project = project;
|
|
||||||
self.trigger(self.project);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,25 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'reflux', 'app/actions/project', 'app/resources'
|
|
||||||
], function(Reflux, ProjectActions, resources) {
|
|
||||||
var resource = resources.projects;
|
|
||||||
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: ProjectActions,
|
|
||||||
onRun: function(projectName) {
|
|
||||||
resource.sync('run', {projectName: projectName}, function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onReadAll: function(params) {
|
|
||||||
var self = this;
|
|
||||||
resource.sync('readAll', params, function(err, projects) {
|
|
||||||
if (err) throw err;
|
|
||||||
self.trigger(projects);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,65 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'underscore', 'reflux', 'app/actions/build', 'app/connect'
|
|
||||||
], function(
|
|
||||||
_, Reflux, BuildActions, connect
|
|
||||||
) {
|
|
||||||
var Store = Reflux.createStore({
|
|
||||||
listenables: BuildActions,
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
// the only purpose of this hash to reconnect all the time
|
|
||||||
// except first, see notes at using
|
|
||||||
this.connectedResourcesHash = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
onReadTerminalOutput: function(build) {
|
|
||||||
var self = this,
|
|
||||||
output = [],
|
|
||||||
resourceName = 'build' + build.id;
|
|
||||||
|
|
||||||
var connectToBuildDataResource = function() {
|
|
||||||
// reconnect for get data below (at subscribe), coz
|
|
||||||
// data emitted only once during connect
|
|
||||||
if (self.connectedResourcesHash[resourceName]) {
|
|
||||||
connect.resource(resourceName).reconnect();
|
|
||||||
} else {
|
|
||||||
self.connectedResourcesHash[resourceName] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
connect.resource(resourceName).subscribe('data', function(data) {
|
|
||||||
var lastLine = _(self.lines).last();
|
|
||||||
if (lastLine && (_(data.lines).first().number === lastLine.number)) {
|
|
||||||
self.lines = _(self.lines).initial();
|
|
||||||
}
|
|
||||||
self.lines = self.lines.concat(data.lines);
|
|
||||||
self.trigger({
|
|
||||||
buildId: build.id,
|
|
||||||
name: 'Console for build #' + build.id,
|
|
||||||
data: _(self.lines).pluck('text')
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.lines = [];
|
|
||||||
this.currentLine = '';
|
|
||||||
|
|
||||||
// create data resource for completed build
|
|
||||||
if (build.completed) {
|
|
||||||
connect.resource('projects').sync(
|
|
||||||
'createBuildDataResource',
|
|
||||||
{buildId: build.id},
|
|
||||||
function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
connectToBuildDataResource();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
connectToBuildDataResource();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Store;
|
|
||||||
});
|
|
@ -1,9 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
define(['underscore', 'shared/utils'], function(_, sharedUtils) {
|
|
||||||
var utils = {};
|
|
||||||
|
|
||||||
_(utils).extend(sharedUtils);
|
|
||||||
|
|
||||||
return utils;
|
|
||||||
});
|
|
34
transforms/jade.js
Normal file
34
transforms/jade.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var through = require('through'),
|
||||||
|
jade = require('react-jade');
|
||||||
|
|
||||||
|
module.exports = function(fileName, options) {
|
||||||
|
if (!/\.jade$/i.test(fileName)) {
|
||||||
|
return through();
|
||||||
|
}
|
||||||
|
|
||||||
|
var template = '';
|
||||||
|
return through(
|
||||||
|
function(chunk) {
|
||||||
|
template += chunk.toString();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
options.filename = fileName;
|
||||||
|
options.globalReact = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
template = jade.compileClient(template, options);
|
||||||
|
} catch (e) {
|
||||||
|
this.emit('error', e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleBody = 'var React = require("react");\n' +
|
||||||
|
'module.exports = ' + template;
|
||||||
|
|
||||||
|
this.queue(moduleBody);
|
||||||
|
this.queue(null);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
@ -5,23 +5,27 @@ html
|
|||||||
|
|
||||||
link(href="/css/index.css", rel="stylesheet", type="text/css")
|
link(href="/css/index.css", rel="stylesheet", type="text/css")
|
||||||
|
|
||||||
if env === 'development'
|
|
||||||
script(type="text/javascript", src="/js/libs/requirejs/require.js")
|
|
||||||
else
|
|
||||||
script
|
|
||||||
include ../static/js/libs/almond/almond.js
|
|
||||||
|
|
||||||
if env === 'development'
|
//-if env === 'development'
|
||||||
script
|
//-script(type="text/javascript", src="/js/libs/requirejs/require.js")
|
||||||
include ../static/js/requirejs/development.js
|
//-else
|
||||||
else
|
//-script
|
||||||
script
|
//-include ../static/js/libs/almond/almond.js
|
||||||
include ../static/js/requirejs/production.js
|
|
||||||
script
|
|
||||||
include ../static/js/app.build.js
|
|
||||||
|
|
||||||
script(type="text/javascript").
|
//-if env === 'development'
|
||||||
require(['app/app']);
|
//-script
|
||||||
|
//-include ../static/js/requirejs/development.js
|
||||||
|
//-else
|
||||||
|
//-script
|
||||||
|
//-include ../static/js/requirejs/production.js
|
||||||
|
//-script
|
||||||
|
//-include ../static/js/app.build.js
|
||||||
|
|
||||||
|
//-script(type="text/javascript").
|
||||||
|
//-require(['app/app']);
|
||||||
|
|
||||||
body
|
body
|
||||||
#content
|
#content
|
||||||
|
|
||||||
|
script
|
||||||
|
include ../static/js/app.build.js
|
||||||
|
Loading…
Reference in New Issue
Block a user