Skip to content

Commit

Permalink
Merge pull request #1911 from tardyp/dataoptims
Browse files Browse the repository at this point in the history
Dataoptims
  • Loading branch information
tardyp committed Nov 8, 2015
2 parents 24e51f8 + 4773144 commit 1cd324e
Show file tree
Hide file tree
Showing 51 changed files with 896 additions and 2,240 deletions.
2 changes: 2 additions & 0 deletions master/docs/relnotes/index.rst
Expand Up @@ -20,6 +20,8 @@ Master
Features
~~~~~~~~

* Builders ui page has improved tag filtering capabilities

Fixes
~~~~~

Expand Down
2 changes: 1 addition & 1 deletion www/base/guanlecoja/config.coffee
Expand Up @@ -52,7 +52,7 @@ config =
files: ["reconnecting-websocket.js"]
'buildbot-data':
version: '~1.0.14'
files: 'dist/scripts.js'
files: 'dist/buildbot-data.js'

testdeps:
"angular-mocks":
Expand Down
Expand Up @@ -13,7 +13,7 @@ class Builder extends Controller
sref: "builders"
,
caption: builder.name
sref: "builder({builder:#{builder.id}})"
sref: "builder({builder:#{builder.builderid}})"
]
recentStorage.addBuilder
link: "#/builders/#{builder.builderid}"
Expand Down
50 changes: 43 additions & 7 deletions www/base/src/app/builders/builders.controller.coffee
Expand Up @@ -31,28 +31,64 @@ class Builders extends Controller

$scope.tags_filter = $location.search()["tags"]
$scope.tags_filter ?= []
$log.debug "params", $location.search()
if not angular.isArray($scope.tags_filter)
$scope.tags_filter = [$scope.tags_filter]

$scope.$watch "tags_filter", (tags, old) ->
if old?
$log.debug "go", tags
$location.search("tags", tags)
, true

$scope.isBuilderFiltered = (builder, index) ->

# filter out inactive builders
if not $scope.settings.show_old_builders.value and not $scope.hasActiveMaster(builder)
return false
if $scope.tags_filter.length == 0

pluses = _.filter($scope.tags_filter, (tag) -> tag.indexOf("+") == 0)
minuses = _.filter($scope.tags_filter, (tag) -> tag.indexOf("-") == 0)

# First enforce that we have no tag marked '-'
for tag in minuses
if builder.tags.indexOf(tag.slice(1)) >= 0
return false

# if only minuses or no filter
if $scope.tags_filter.length == minuses.length
return true
for tag in builder.tags
if $scope.tags_filter.indexOf(tag) >= 0

# Then enforce that we have all the tags marked '+'
for tag in pluses
if builder.tags.indexOf(tag.slice(1)) < 0
return false

# Then enforce that we have at least one of the tag (marked '+' or not)
for tag in $scope.tags_filter
if tag.indexOf("+") == 0
tag = tag.slice(1)
if builder.tags.indexOf(tag) >= 0
return true
return false

$scope.isTagFiltered = (tag) ->
return $scope.tags_filter.length == 0 or $scope.tags_filter.indexOf(tag) >= 0
return $scope.tags_filter.length == 0 or $scope.tags_filter.indexOf(tag) >= 0 or
$scope.tags_filter.indexOf('+' + tag) >= 0 or $scope.tags_filter.indexOf('-' + tag) >= 0

$scope.toggleTag = (tag) ->
if tag.indexOf('+') == 0
tag = tag.slice(1)
if tag.indexOf('-') == 0
tag = tag.slice(1)
i = $scope.tags_filter.indexOf(tag)
if i < 0
iplus = $scope.tags_filter.indexOf("+" + tag)
iminus = $scope.tags_filter.indexOf("-" + tag)
if i < 0 and iplus < 0 and iminus < 0
$scope.tags_filter.push("+" + tag)
else if iplus >= 0
$scope.tags_filter.splice(iplus, 1)
$scope.tags_filter.push('-' + tag)
else if iminus >= 0
$scope.tags_filter.splice(iminus, 1)
$scope.tags_filter.push(tag)
else
$scope.tags_filter.splice(i, 1)
Expand Down
21 changes: 21 additions & 0 deletions www/base/src/app/builders/builders.tpl.jade
Expand Up @@ -5,6 +5,27 @@
th Builder Name
th Builds
th
span(ng-init="help=false", ng-click="help=!help")
i.fa.fa-question-circle(style="position:relative")
.popover.bottom.anim-popover(ng-if="help",
style="display:block;min-width:600px;left:-300px;top:30px")
h5.popover-title
| Tags filtering
.popover-content
p
b
pre +{tag}
| all tags with '+' must be present in the builder tags
p
b
pre -{tag}
| no tags with '-' must be present in the builder tags
p
b
pre {tag}
| at least one of the filtered tag should be present
p url bar is updated with you filter configuration, so you can bookmark your filters!
.arrow
span(ng-show="tags_filter.length==0") Tags
span(ng-show="tags_filter.length < 5", ng-repeat="tag in tags_filter")
span.label.label-success(ng-click="toggleTag(tag)")
Expand Down
Expand Up @@ -54,8 +54,8 @@ class Buildrequest extends Controller
caption: builder.name
sref: "builder({builder:#{buildrequest.builderid}})"
,
caption: buildrequest.id
sref: "buildrequest({buildrequest:#{buildrequest.id}})"
caption: buildrequest.buildrequestid
sref: "buildrequest({buildrequest:#{buildrequest.buildrequestid}})"
]

glBreadcrumbService.setBreadcrumb(breadcrumb)
Expand Down
Expand Up @@ -30,7 +30,7 @@ describe 'buildrequest controller', ->
dataService.when('buildsets/1', [{buildsetid: 1}])
controller = createController()
$rootScope.$apply()
expect(dataService.get).toHaveBeenCalledWith('buildrequests', 1, jasmine.any(Object))
expect(dataService.get).toHaveBeenCalledWith('buildrequests', 1)
$scope.buildrequest.claimed = true
dataService.when('builds', {buildrequestid: 1}, [{buildid: 1}, {buildid: 2}])
$rootScope.$apply()
Expand Down
8 changes: 4 additions & 4 deletions www/base/src/app/builders/log/log.controller.coffee
Expand Up @@ -18,14 +18,14 @@ class Log extends Controller
sref: "builders"
,
caption: builder.name
sref: "builder({builder:#{builder.id}})"
sref: "builder({builder:#{builder.builderid}})"
,
caption: build.number
sref: "build({builder:#{builder.id}, build:#{build.number}})"
sref: "build({builder:#{builder.builderid}, build:#{build.number}})"
,
caption: step.name
sref: "step({builder:#{builder.id}, build:#{build.number}, step:#{step.number}})"
sref: "step({builder:#{builder.builderid}, build:#{build.number}, step:#{step.number}})"
,
caption: log.name
sref: "log({builder:#{builder.id}, build:#{build.number}, step:#{step.number}, log:'#{log.slug}'})"
sref: "log({builder:#{builder.builderid}, build:#{build.number}, step:#{step.number}, log:'#{log.slug}'})"
]
Expand Up @@ -20,8 +20,8 @@ class Logviewer extends Directive
log = self.scope.log
self.scope.raw_url = "/api/v2/logs/#{log.logid}/raw"
if log.type == 'h'
log.getContents().then (content) ->
self.scope.content = $sce.trustAs($sce.HTML, content[0].content)
restService.get("logs/#{log.logid}/contents").then (content) ->
self.scope.content = $sce.trustAs($sce.HTML, content.logchunks[0].content)

lines:
get: (index, count) ->
Expand All @@ -33,7 +33,7 @@ class Logviewer extends Directive
requestId = "#{index}_#{count}"
if not self.requests[requestId]?
self.requests[requestId] = $q (resolve) ->
restService.get("#{log._endpoint}/#{log.name}/contents", offset:index, limit:count).then (content) ->
restService.get("logs/#{log.logid}/contents", offset:index, limit:count).then (content) ->
content = content.logchunks
# log.getContents(offset:index, limit:count).then (content) ->
ret = []
Expand Down
6 changes: 3 additions & 3 deletions www/base/src/app/builders/step/step.controller.coffee
Expand Up @@ -15,13 +15,13 @@ class Step extends Controller
sref: "builders"
,
caption: builder.name
sref: "builder({builder:#{builder.id}})"
sref: "builder({builder:#{builder.builderid}})"
,
caption: build.number
sref: "build({builder:#{builder.id}, build:#{build.number}})"
sref: "build({builder:#{builder.builderid}, build:#{build.number}})"
,
caption: step.name
sref: "step({builder:#{builder.id}, build:#{build.number}, step:#{step.number}})"
sref: "step({builder:#{builder.builderid}, build:#{build.number}, step:#{step.number}})"
]
step.loadLogs()
$scope.step = publicFieldsFilter(step)
Expand Up @@ -27,34 +27,34 @@ describe 'buildrequest summary controller', ->

it 'should get the buildrequest', ->
buildrequests = [{buildrequestid: 1}]
dataService.when('buildrequests/1', {subscribe: true}, buildrequests)
dataService.when('buildrequests/1', buildrequests)
expect(dataService.get).not.toHaveBeenCalled()
controller = createController()
expect(dataService.get).toHaveBeenCalledWith('buildrequests', $scope.buildrequestid, {subscribe: true})
expect(dataService.get).toHaveBeenCalledWith('buildrequests', $scope.buildrequestid)
$scope.$apply()
expect($scope.buildrequest.buildrequestid).toBe(1)

it 'should query for builds again if first query returns 0', ->
buildrequests = [{buildrequestid: 1}]
dataService.when('buildrequests/1', {subscribe: true}, buildrequests)
dataService.when('buildrequests/1', buildrequests)
builds = []
dataService.when('builds', {subscribe: true, buildrequestid: 1}, builds)
dataService.when('builds', {buildrequestid: 1}, builds)

controller = createController()
expect(dataService.get).toHaveBeenCalledWith('buildrequests', 1, {subscribe: true})
expect(dataService.get).toHaveBeenCalledWith('buildrequests', 1)
$scope.$apply()

$scope.buildrequest.claimed = true
$scope.$apply()
expect(dataService.get).toHaveBeenCalledWith('builds', {subscribe: true, buildrequestid: 1})
expect(dataService.get).toHaveBeenCalledWith('builds', {buildrequestid: 1})
lastCount = dataService.get.calls.count()
expect($scope.builds.length).toBe(builds.length)

builds = [{buildid: 1}, {buildid: 2}]
dataService.when('builds', {subscribe: true, buildrequestid: 1}, builds)
dataService.when('builds', {buildrequestid: 1}, builds)

$timeout.flush()
expect(dataService.get).toHaveBeenCalledWith('builds', {subscribe: true, buildrequestid: 1})
expect(dataService.get).toHaveBeenCalledWith('builds', {buildrequestid: 1})
count = dataService.get.calls.count()
expect(count).toBe(lastCount + 1)
expect($scope.builds.length).toBe(builds.length)
Expand Up @@ -24,7 +24,7 @@ describe 'buildsummary controller', ->
dataService.when('builds/1', [{buildid: 1, builderid: 1}])
dataService.when('builders/1', [{builderid: 1}])
dataService.when('builds/1/steps', [{builderid: 1, stepid: 1, number: 1}])
dataService.when('builds/1/steps/1/logs', [{stepid: 1, logid: 1}, {stepid: 1, logid: 2}])
dataService.when('steps/1/logs', [{stepid: 1, logid: 1}, {stepid: 1, logid: 2}])

beforeEach(inject(injected))

Expand Down
15 changes: 6 additions & 9 deletions www/data_module/guanlecoja/config.coffee
Expand Up @@ -14,7 +14,7 @@ gulp.task "publish", ['default'], ->
bower_json =
name: "buildbot-data"
version: "1.0.15"
main: ["scripts.js"]
main: ["buildbot-data.js"]
moduleType: [],
license: "MIT",
ignore: []
Expand Down Expand Up @@ -47,27 +47,24 @@ config =
build: 'dist'

sourcemaps: true
output_scripts: "buildbot-data.js"
### ###########################################################################################
# Bower dependancies configuration
### ###########################################################################################
bower:
deps:
tabex:
version: '~1.0.3'
files: 'dist/tabex.js'
dexie:
version: '~1.1.0'
files: 'dist/latest/Dexie.js'
testdeps:
angular:
version: ANGULAR_TAG
files: 'angular.js'
'angular-mocks':
version: ANGULAR_TAG
files: 'angular-mocks.js'
'lodash':
version: '~3.10.0'
files: 'lodash.js'
# as angular is a test deps, the tests need to be loaded first!
karma:
files: [ "tests.js", "scripts.js"]
files: [ "tests.js", "buildbot-data.js"]

ngclassify: (config) ->
return {
Expand Down
61 changes: 61 additions & 0 deletions www/data_module/src/classes/base.service.coffee
@@ -0,0 +1,61 @@
class Base extends Factory
constructor: (dataService, socketService, dataUtilsService) ->
return class BaseInstance
constructor: (object, @_endpoint, childEndpoints = []) ->
if not angular.isString(@_endpoint)
throw new TypeError("Parameter 'endpoint' must be a string, not #{typeof @endpoint}")

# add object fields to the instance
@update(object)

# generate loadXXX functions
@constructor.generateFunctions(childEndpoints)

# get the id of the class type
classId = dataUtilsService.classId(@_endpoint)
@_id = @[classId]

# reset endpoint to base
if @_id?
@_endpoint = dataUtilsService.type(@_endpoint)
# subscribe for WebSocket events
@subscribe()

update: (o) ->
angular.merge(@, o)

get: (args...) ->
dataService.get(@_endpoint, @_id, args...)

subscribe: ->
listener = (data) =>
key = data.k
message = data.m
# filter for relevant message
streamRegex = ///^#{@_endpoint}\/#{@_id}\/\w+$///g
# update when the key matches the instance
if streamRegex.test(key) then @update(message)
@_unsubscribeEventListener = socketService.eventStream.subscribe(listener)
# _listenerId is required by the stopConsuming logic in dataService
@_listenerId = listener.id

unsubscribe: ->
# unsubscribe childs
for k, v of this
if angular.isArray(v)
v.forEach (e) -> e.unsubscribe() if e instanceof BaseInstance
@_unsubscribeEventListener()

# generate endpoint functions for the class
@generateFunctions: (endpoints) ->
endpoints.forEach (e) =>
# capitalize endpoint names
E = dataUtilsService.capitalize(e)
# adds loadXXX functions to the prototype
@::["load#{E}"] = (args...) ->
p = @get(e, args...)
@[e] = p.getArray()
return p
# adds getXXX functions to the prototype
@::["get#{E}"] = (args...) ->
return @get(e, args...)

0 comments on commit 1cd324e

Please sign in to comment.