Skip to content

Commit

Permalink
Merge pull request #1703 from tothandras/data_service
Browse files Browse the repository at this point in the history
Frontend data service
  • Loading branch information
tardyp committed Jun 22, 2015
2 parents 65c32ad + 5f71f66 commit ab3669f
Show file tree
Hide file tree
Showing 36 changed files with 1,326 additions and 9 deletions.
9 changes: 0 additions & 9 deletions www/console_view/Gruntfile.coffee

This file was deleted.

3 changes: 3 additions & 0 deletions www/data_module/.bowerrc
@@ -0,0 +1,3 @@
{
"directory": "libs"
}
16 changes: 16 additions & 0 deletions www/data_module/.editorconfig
@@ -0,0 +1,16 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{js,json}]
indent_size = 2

[*.md]
trim_trailing_whitespace = false
9 changes: 9 additions & 0 deletions www/data_module/.gitignore
@@ -0,0 +1,9 @@
# Bower library folder
libs

# Build folder
dist

# Node package manager
node_modules
npm-debug.log
27 changes: 27 additions & 0 deletions www/data_module/README.md
@@ -0,0 +1,27 @@
# Buildbot data module

Buildbot data module is an AngularJS module for Buildbot nine clients.

## Installation

```
$ bower install buildbot-data
```

## Adding dependency to your project

```
angular.module('myModule', ['bbData']);
```

## Building
```
$ npm install
$ gulp
```
## Running tests
```
$ npm install
$ karma start
```
12 changes: 12 additions & 0 deletions www/data_module/bower.json
@@ -0,0 +1,12 @@
{
"name": "buildbot-data",
"version": "1.0.0",
"description": "Buildbot AngularJS bbData module",
"main": "dist/buildbot-data.js",
"dependencies": {
"angular": "~1.4.1"
},
"devDependencies": {
"angular-mocks": "~1.4.1"
}
}
69 changes: 69 additions & 0 deletions www/data_module/gulpfile.coffee
@@ -0,0 +1,69 @@
################################################################################
# Gulp
################################################################################

gulp = require('gulp')
# gulp plugins & dependencies
p = require('gulp-load-plugins')()
del = require('del')
# scoped release tasks for gulp
require('gulp-release-tasks')(gulp)

################################################################################
# Arguments
################################################################################

# --watch
WATCH = p.util.env.watch?

################################################################################
# Configuration
################################################################################

c =
fileName: 'buildbot-data'
karma:
action: if WATCH then 'watch' else 'run'
configFile: 'karma.conf.coffee'
classify:
appName: 'bbData'
provider:
suffix: 'Service'

paths =
src: 'src'
build: 'dist'

files =
coffee: [
"#{paths.src}/**/*.module.coffee"
"#{paths.src}/**/!(*.spec).coffee"
]

################################################################################
# Tasks
################################################################################

gulp.task 'clean', (cb) ->
del paths.build, cb

gulp.task 'build', ['clean'], ->
gulp.src files.coffee
.pipe p.ngClassify(c.classify)
.pipe p.coffee()
.pipe p.concat("#{c.fileName}.js")
.pipe gulp.dest(paths.build)
.pipe p.ngAnnotate()
.pipe p.uglify()
.pipe p.rename("#{c.fileName}.min.js")
.pipe gulp.dest(paths.build)

gulp.task 'test', ['bower'], ->
# pass in a directory that doesn't exist
# karma will use the files specified in the configuration
gulp.src('test')
.pipe p.karma(c.karma)

gulp.task 'bower', -> return p.bower()

gulp.task 'default', ['clean', 'test', 'build']
54 changes: 54 additions & 0 deletions www/data_module/karma.conf.coffee
@@ -0,0 +1,54 @@
module.exports = (config) ->
config.set
# Base path, that will be used to resolve files and exclude
basePath: ''

# Testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine']

# List of files / patterns to load in the browser
files: [
'libs/angular/angular.js'
'libs/angular-mocks/angular-mocks.js'
'src/**/*.module.coffee'
'src/**/*.coffee'
]

# List of files / patterns to exclude
exclude: []

# Web server port
port: 9876

# Level of logging
# Possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO

# Start these browsers, currently available:
# - Chrome
# - ChromeCanary
# - Firefox
# - Opera
# - Safari (only Mac)
# - PhantomJS
# - IE (only Windows)
browsers: [
'PhantomJS'
]

# Continuous Integration mode
# enable / disable watching file and executing tests whenever any file changes
autoWatch: false
singleRun: true

colors: true

preprocessors: '**/*.coffee': ['ng-classify', 'coffee']

ngClassifyPreprocessor:
options:
# any options supported by ng-classify
# https://github.com/CaryLandholt/ng-classify#api
appName: 'bbData'
provider:
suffix: 'Service'
34 changes: 34 additions & 0 deletions www/data_module/package.json
@@ -0,0 +1,34 @@
{
"name": "buildbot-data",
"version": "1.0.0",
"description": "Buildbot AngularJS bbData module",
"readme": "README.md",
"devDependencies": {
"coffee-script": "*",
"del": "^1.2.0",
"gulp": "~3.8.6",
"gulp-bower": "0.0.10",
"gulp-coffee": "^2.3.1",
"gulp-concat": "^2.5.2",
"gulp-karma": "0.0.4",
"gulp-load-plugins": "^1.0.0-rc.1",
"gulp-ng-annotate": "^1.0.0",
"gulp-ng-classify": "^4.0.1",
"gulp-release-tasks": "0.0.3",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^1.2.0",
"gulp-util": "^3.0.5",
"jasmine-core": "^2.3.4",
"karma": "^0.12.36",
"karma-coffee-preprocessor": "*",
"karma-jasmine": "^0.2.2",
"karma-ng-classify-preprocessor": "*",
"karma-phantomjs-launcher": "*",
"phantomjs": "^1.9.17"
},
"dependencies": {},
"engines": {
"node": ">=0.10.20",
"npm": ">=1.4.10"
}
}
55 changes: 55 additions & 0 deletions www/data_module/src/classes/base.service.coffee
@@ -0,0 +1,55 @@
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]

# 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
68 changes: 68 additions & 0 deletions www/data_module/src/classes/base.service.spec.coffee
@@ -0,0 +1,68 @@
describe 'Base class', ->
beforeEach module 'bbData'

Base = dataService = socketService = $q = null
injected = ($injector) ->
Base = $injector.get('Base')
dataService = $injector.get('dataService')
socketService = $injector.get('socketService')
$q = $injector.get('$q')

beforeEach(inject(injected))

it 'should be defined', ->
expect(Base).toBeDefined()

it 'should merge the passed in object with the instance', ->
object = a: 1, b: 2
base = new Base(object, 'ab')
expect(base.a).toEqual(object.a)
expect(base.b).toEqual(object.b)

it 'should have loadXxx function for child endpoints', ->
children = ['a', 'bcd', 'ccc']
base = new Base({}, 'ab', children)
for e in children
E = e[0].toUpperCase() + e[1..-1].toLowerCase()
expect(angular.isFunction(base["load#{E}"])).toBeTruthy()

it 'should subscribe a listener to socket service events', ->
expect(socketService.eventStream.listeners.length).toBe(0)
base = new Base({}, 'ab')
expect(socketService.eventStream.listeners.length).toBe(1)

it 'should remove the listener on unsubscribe', ->
expect(socketService.eventStream.listeners.length).toBe(0)
base = new Base({}, 'ab')
expect(socketService.eventStream.listeners.length).toBe(1)
base.unsubscribe()
expect(socketService.eventStream.listeners.length).toBe(0)

it 'should update the instance when the event key matches', ->
object = buildid: 1, a: 2, b: 3
base = new Base(object, 'builds')
expect(base.a).toEqual(object.a)
socketService.eventStream.push
k: 'builds/2/update'
m: a: 3
expect(base.a).toEqual(object.a)
socketService.eventStream.push
k: 'builds/1/update'
m:
a: 3
c: 4
expect(base.a).toEqual(3)
expect(base.c).toEqual(4)

it 'should remove the listeners of child endpoints on unsubscribe', ->
base = new Base({}, '', ['ccc'])
child = new Base({}, '')
response = [child]
p = $q.resolve(response)
p.getArray = -> return response
spyOn(dataService, 'get').and.returnValue(p)
base.loadCcc()
expect(base.ccc).toEqual(response)
expect(socketService.eventStream.listeners.length).toBe(2)
base.unsubscribe()
expect(socketService.eventStream.listeners.length).toBe(0)
12 changes: 12 additions & 0 deletions www/data_module/src/classes/build.service.coffee
@@ -0,0 +1,12 @@
class Build extends Factory
constructor: (Base, dataService) ->
return class BuildInstance extends Base
constructor: (object, endpoint) ->
endpoints = [
'changes' # /changes
'properties' # /properties
'steps' # /steps/:name
# /steps/:stepid
]

super(object, endpoint, endpoints)
14 changes: 14 additions & 0 deletions www/data_module/src/classes/builder.service.coffee
@@ -0,0 +1,14 @@
class Builder extends Factory
constructor: (Base, dataService) ->
return class BuilderInstance extends Base
constructor: (object, endpoint) ->
endpoints = [
'builds' # /builds/:buildid
'buildrequests' # /buildrequests/:buildrequestid
'forceschedulers' # /forceschedulers
'buildslaves' # /buildslaves/:buildslaveid
# /buildslaves/:name
'masters' # /masters/:masterid
]

super(object, endpoint, endpoints)

0 comments on commit ab3669f

Please sign in to comment.