diff --git a/master/buildbot/www/static/js/lib/fakeChangeStore.js b/master/buildbot/www/static/js/lib/fakeChangeStore.js new file mode 100644 index 00000000000..391f3ee6638 --- /dev/null +++ b/master/buildbot/www/static/js/lib/fakeChangeStore.js @@ -0,0 +1,17 @@ +define( + [ + "dojo/_base/declare", + "lib/fakeStore" + ], + function(declare, fakeStore) { + var data=[]; + return declare(fakeStore, { + data:data, + fields: ["changeid", "revision", "committer", "files", "comments" ], + addData: function(o) { + /* persist data over reload */ + data = this.data; + this.put(o); + } + }); + }); diff --git a/master/buildbot/www/static/js/lib/fakeStore.js b/master/buildbot/www/static/js/lib/fakeStore.js new file mode 100644 index 00000000000..dfb2098f510 --- /dev/null +++ b/master/buildbot/www/static/js/lib/fakeStore.js @@ -0,0 +1,39 @@ +define( + [ + "dojo/_base/declare", + "dojo/store/Memory" + ], + function(declare, Memory) { + return declare([Memory], { + fields: ["field1"], + constructor: function(args){ + declare.safeMixin(this,args); + this.interval = setInterval(dojo.hitch(this, this.addSomeData), 1000); //simulate adding some data every second + }, + addSomeData: function() { + var randomfeed = "sdlkjs alkdj alsdjl ksdj lsajldkjaslkdj asdlkja iwjedo ajlskj lhsl"; + var curId=0; + if (this.data.length>0) { + curId = this.data[this.data.length-1].id+1; + } + var o = {id:curId}; + this.curId+=1; + for (var i=0; i < this.fields.length; i+=1) { + var l = Math.floor(Math.random()*20); + var v = ""; + for (var j=0; j

Error in parsing haml!

"+Haml.html_escape(str)+"

"+Haml.html_escape(e.toString())+"
"; + } } } /* dojo/AMD magic: require( ["lib/haml!./template/mytemplate.haml"], function(template){ ... diff --git a/master/buildbot/www/static/js/lib/router.js b/master/buildbot/www/static/js/lib/router.js index 462d9c66865..7ce32a04003 100644 --- a/master/buildbot/www/static/js/lib/router.js +++ b/master/buildbot/www/static/js/lib/router.js @@ -13,8 +13,8 @@ // // Copyright Buildbot Team Members -define(["dojo/_base/declare", "dojo/_base/connect","dojo/_base/array","dojo/dom", "put-selector/put","dojo/hash", "dojo/io-query"], - function(declare, connect, array, dom, put, hash, ioquery) { +define(["dojo/_base/declare", "dojo/_base/connect","dojo/_base/array","dojo/dom", "put-selector/put","dojo/hash", "dojo/io-query", "dojo/dom-class"], + function(declare, connect, array, dom, put, hash, ioquery, domclass) { "use strict"; /* allow chrome to display correctly generic errbacks from dojo */ console.error = function(err) { @@ -131,11 +131,11 @@ define(["dojo/_base/declare", "dojo/_base/connect","dojo/_base/array","dojo/dom" }); }); if (nav) { - nav.classList.add("active"); + domclass.add(nav, "active"); } } else { /* match */ if (nav) { - nav.classList.remove("active"); + domclass.remove(nav, "active"); } } })); diff --git a/master/buildbot/www/static/js/lib/ui/build.js b/master/buildbot/www/static/js/lib/ui/build.js index 909c330a331..9ffd927c0c7 100644 --- a/master/buildbot/www/static/js/lib/ui/build.js +++ b/master/buildbot/www/static/js/lib/ui/build.js @@ -13,11 +13,70 @@ // // Copyright Buildbot Team Members -define(["dojo/_base/declare", "lib/ui/base"], function(declare, Base) { +define(["dojo/_base/declare", "lib/ui/base", + "lib/haml!./templates/build.haml" + ], function(declare, Base, template) { "use strict"; return declare([Base], { + templateFunc : template, constructor: function(args){ declare.safeMixin(this,args); - } + }, + loadMoreContext: function(){ + var deferred = new dojo.Deferred(); + this.builderName = this.path_components[1].toString(); + this.number = this.path_components[2].toString(); + /* simulate loading of all needed stuff from json API */ + setTimeout(dojo.hitch(this, function(){ + this.sourceStamps = [ { changes: { changeid:"changeid1", + revision:"revision1", + committer: "me@anonymous.com", + files: ["path/to/file1", + "path/to/file2"], + comments: "this code should pas CI" }}]; + this.reason = "change committed"; + this.blame = ["me@anonymous.com"]; + this.properties = [ { name:"prop1", value:"value1", source:"fake"} ]; + this.times = ['two hours ago', 'last hour']; + this.when_time = "soon"; + this.when = "~5min"; + this.text = "build succeeded"; + this.results = "SUCCESS" + this.slave = "slave1" + this.slave_url = "#/slaves/"+this.slave + this.steps = [ {name:"build step", + text:"make done", + results:"SUCCESS", + isStarted:true, + isFinished:true, + statistics:[], + times:[0,1], + expectations: [], + eta:null, + urls:{url1:"./url1.html"}, + step_number: 1, + hidden:false, + logs:{stdio:"./stdio"}}, + {name:"test step", + text:"test done", + results:"SUCCESS", + isStarted:true, + isFinished:true, + statistics:[], + times:[0,1], + expectations: [], + eta:null, + urls:{url1:"url2.html"}, + step_number: 2, + hidden:false, + logs:{stdio:"stdio"}}]; + this.currentStep="test step"; + this.results_class = "btn-success" + deferred.callback({success: true}); }), 100); + return deferred; + }, + isFinished: function() { + return this.number<5; + } }); }); diff --git a/master/buildbot/www/static/js/lib/ui/changes.js b/master/buildbot/www/static/js/lib/ui/changes.js index 909c330a331..d4db7b1a968 100644 --- a/master/buildbot/www/static/js/lib/ui/changes.js +++ b/master/buildbot/www/static/js/lib/ui/changes.js @@ -13,11 +13,56 @@ // // Copyright Buildbot Team Members -define(["dojo/_base/declare", "lib/ui/base"], function(declare, Base) { - "use strict"; - return declare([Base], { - constructor: function(args){ - declare.safeMixin(this,args); - } - }); -}); +define(["dojo/_base/declare", "lib/ui/base", "dgrid/OnDemandGrid", + "dgrid/Selection", "dgrid/Keyboard","dgrid/extensions/ColumnHider", + "dojo/store/Observable", "lib/fakeChangeStore", + "dojo/text!./templates/changes.html"], + function(declare, Base, Grid, Selection, Keyboard, Hider, observable, Store, template) { + "use strict"; + return declare([Base], { + templateString:template, + constructor: function(args){ + declare.safeMixin(this,args); + }, + postCreate: function(){ + this.store = observable(new Store()); + var maingrid = new (declare([Grid, Selection, Keyboard, Hider]))({ + loadingMessage: "loading...", + store: this.store, + minRowsPerPage: 15, + maxRowsPerPage: 15, + cellNavigation:false, + tabableHeader: false, + columns: { + id: {label:"ID", width:"10px"}, + changeid: "Change ID", + revision: + {label: "Revision", + sortable: false}, + committer: + {label: "committer", + sortable: false}, + comments: + {label: "Comments", + sortable: false} + } + }, this.maingrid_node); + maingrid.on(".dgrid-row:dblclick", dojo.hitch(this, this.rowDblClick)); + maingrid.on("dgrid-select", dojo.hitch(this, this.select)); + maingrid.refresh(); + this.maingrid = maingrid; + }, + select: function(event) { + var _this = this; + if (this.withSelect) { + this.withSelect(arrayUtil.map(event.rows, function(row){ return _this.store.get(row.id); })); + } + }, + rowDblClick : function(evt) { + }, + destroy: function(){ + this.maingrid.destroy(); + this.store.destroy(); + } + }); + }); diff --git a/master/buildbot/www/static/js/lib/ui/home.js b/master/buildbot/www/static/js/lib/ui/home.js index 909c330a331..563470b5920 100644 --- a/master/buildbot/www/static/js/lib/ui/home.js +++ b/master/buildbot/www/static/js/lib/ui/home.js @@ -13,9 +13,12 @@ // // Copyright Buildbot Team Members -define(["dojo/_base/declare", "lib/ui/base"], function(declare, Base) { +define(["dojo/_base/declare", "lib/ui/base", + "dojo/text!./templates/home.html" + ], function(declare, Base, template) { "use strict"; return declare([Base], { + templateString : template, constructor: function(args){ declare.safeMixin(this,args); } diff --git a/master/buildbot/www/static/js/lib/ui/templates/build.haml b/master/buildbot/www/static/js/lib/ui/templates/build.haml new file mode 100644 index 00000000000..55c3c87ea1f --- /dev/null +++ b/master/buildbot/www/static/js/lib/ui/templates/build.haml @@ -0,0 +1,43 @@ +.container-fluid + %ul.breadcrumb + %li + %a{href:"../"}<> #{ builderName } + %span.divider #{"/"} + %li.active Build ##{number} + .row-fluid + .span5 + .well + :if !isFinished() + %h3 Build In Progress: + :if when_time + %p ETA: #{ when_time } [ #{ when } ] + %li.form-inline>= currentStep +   + .btn.btn-inverse.btn-mini{data-dojo-attach-point:"stop_build_node"} Stop Build + :if isFinished() + %h3.form-inline Results: +   + .btn.disabled{class:results_class} #{text} + .well + %h3.form-inline BuildSlave: + :if this.slave_url + %a{href:slave_url}= slave + :if !this.slave_url + %span= slave + .well + %h3.form-inline Reason: + %p= reason + .well + %h3 Steps and Logfiles: + %ol + :each step in steps + %li #{step.name} + %ol + :each name, url in step.logs + %li + %a{href:url} #{name} + :each name, url in step.urls + %li + %a{href:url} #{name} + .span7.well + %h3 build properties diff --git a/master/buildbot/www/static/js/lib/ui/templates/changes.html b/master/buildbot/www/static/js/lib/ui/templates/changes.html new file mode 100644 index 00000000000..0f75135041d --- /dev/null +++ b/master/buildbot/www/static/js/lib/ui/templates/changes.html @@ -0,0 +1,21 @@ +
+ +
+
+

Last changes coming into the system

+
+
+
+
+
+
+
+

Associated Files

+
+
+
+
diff --git a/master/buildbot/www/static/js/lib/ui/templates/home.html b/master/buildbot/www/static/js/lib/ui/templates/home.html new file mode 100644 index 00000000000..77b28acce6f --- /dev/null +++ b/master/buildbot/www/static/js/lib/ui/templates/home.html @@ -0,0 +1,37 @@ +
+
+
+ +
+
+
+

Welcome to buildbot

+ Probably we should display information about the current config +
+
+
+
    +
  • Buildbot version
  • +
  • Twisted version
  • +
+
+
    +
  • Project name
  • +
  • Project version
  • +
  • Project URL
  • +
+
+
+
+
diff --git a/master/buildbot/www/ui.py b/master/buildbot/www/ui.py index 572efba5094..64ced85daaa 100644 --- a/master/buildbot/www/ui.py +++ b/master/buildbot/www/ui.py @@ -37,3 +37,43 @@ def render(self, request): static_url = self.static_url, ws_url = self.baseurl.replace("http:", "ws:")) return html % contents + +if __name__ == '__main__': + from twisted.application import strports, service + from twisted.web import server, static + from twisted.internet import reactor + class myStaticFile(static.File): + """Fix issue in twisted static implementation + where a 304 Not Modified always returns text/html + which makes chrome complain a lot in its logs""" + def render_GET(self, request): + r = static.File.render_GET(self, request) + if r=="": + request.setHeader('content-type', self.type) + return r + + class WWWService(service.MultiService): + def __init__(self): + service.MultiService.__init__(self) + class fakeConfig(): + www = dict(url="http://localhost:8010/", port=8010) + class fakeMaster(): + config = fakeConfig() + self.master = fakeMaster() + self.setup_site() + self.port_service = strports.service("8010", self.site) + self.port_service.setServiceParent(self) + self.startService() + def setup_site(self): + root = static.Data('placeholder', 'text/plain') + # redirect the root to UI + root.putChild('', resource.RedirectResource(self.master, 'ui/')) + # /ui + root.putChild('ui', UIResource(self.master)) + # /static + staticdir = util.sibpath(__file__, 'static') + + root.putChild('static', myStaticFile(staticdir)) + self.site = server.Site(root) + WWWService() + reactor.run()