Skip to content

Commit 4668907

Browse files
committed
Allow to update device notes column from STF UI. openstf#124
1 parent 26421fd commit 4668907

9 files changed

Lines changed: 135 additions & 7 deletions

File tree

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"eventEmitter": "~4.3.0",
3333
"angular-ladda": "~0.3.1",
3434
"d3": "~3.5.6",
35-
"spin.js": "~2.3.2"
35+
"spin.js": "~2.3.2",
36+
"angular-xeditable": "~0.1.9"
3637
},
3738
"private": true,
3839
"devDependencies": {

lib/db/api.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ dbapi.setDeviceRotation = function(serial, rotation) {
258258
}))
259259
}
260260

261+
dbapi.setDeviceNote = function(serial, note) {
262+
return db.run(r.table('devices').get(serial).update({
263+
notes: note
264+
}))
265+
}
266+
261267
dbapi.setDeviceReverseForwards = function(serial, forwards) {
262268
return db.run(r.table('devices').get(serial).update({
263269
reverseForwards: forwards

lib/units/websocket/index.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,28 @@ module.exports = function(options) {
305305

306306
new Promise(function(resolve) {
307307
socket.on('disconnect', resolve)
308+
// Global messages for all clients using socket.io
309+
//
310+
// Device note
311+
.on('device.note', function(data) {
312+
return dbapi.setDeviceNote(data.serial, data.note)
313+
.then(function() {
314+
return dbapi.loadDevice(data.serial)
315+
})
316+
.then(function(device) {
317+
if(device) {
318+
io.emit('device.change', {
319+
important: true
320+
, data: {
321+
serial: device.serial
322+
, notes: device.notes
323+
}
324+
})
325+
}
326+
})
327+
})
328+
// Client specific messages
329+
//
308330
// Settings
309331
.on('user.settings.update', function(data) {
310332
dbapi.updateUserSettings(user.email, data)

res/app/components/stf/device/device-service.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,12 @@ module.exports = function DeviceServiceFactory($http, socket, EnhanceDeviceServi
210210
})
211211
}
212212

213+
deviceService.updateNote = function (serial, note) {
214+
socket.emit('device.note', {
215+
serial: serial,
216+
note: note
217+
})
218+
}
219+
213220
return deviceService
214221
}

res/app/device-list/column/device-column-service.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var filterOps = {
1818
}
1919
}
2020

21-
module.exports = function DeviceColumnService($filter, gettext) {
21+
module.exports = function DeviceColumnService($filter, $compile, gettext) {
2222
// Definitions for all possible values.
2323
return {
2424
state: DeviceStatusCell({
@@ -252,8 +252,14 @@ module.exports = function DeviceColumnService($filter, gettext) {
252252
return device.provider ? device.provider.name : ''
253253
}
254254
})
255-
, notes: TextCell({
255+
, notes: XEditableCell({
256256
title: gettext('Notes')
257+
, compile: $compile
258+
, scopeRequired: true
259+
, attrs: {
260+
model: 'device.notes'
261+
, onbeforesave: 'updateNote(device.serial, $data)'
262+
}
257263
, value: function(device) {
258264
return device.notes || ''
259265
}
@@ -613,3 +619,38 @@ function DeviceStatusCell(options) {
613619
}
614620
})
615621
}
622+
623+
function XEditableCell(options) {
624+
return _.defaults(options, {
625+
title: options.title
626+
, defaultOrder: 'asc'
627+
, build: function (scope) {
628+
var td = document.createElement('td')
629+
, a = document.createElement('a')
630+
631+
// Ref: http://vitalets.github.io/angular-xeditable/#text-simple
632+
a.setAttribute('href', '#')
633+
a.setAttribute('editable-text', options.attrs.model)
634+
a.setAttribute('onbeforesave', options.attrs.onbeforesave)
635+
636+
a.appendChild(document.createTextNode(options.attrs.model))
637+
td.appendChild(a)
638+
639+
// compile with new scope
640+
options.compile(td)(scope)
641+
return td
642+
}
643+
, update: function(td, item) {
644+
var a = td.firstChild
645+
, t = a.firstChild
646+
t.nodeValue = options.value(item) || 'click to add'
647+
return td
648+
}
649+
, compare: function(a, b) {
650+
return compareIgnoreCase(options.value(a), options.value(b))
651+
}
652+
, filter: function(item, filter) {
653+
return filterIgnoreCase(options.value(item), filter.query)
654+
}
655+
})
656+
}

res/app/device-list/details/device-list-details-directive.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ var patchArray = require('./../util/patch-array')
22

33
module.exports = function DeviceListDetailsDirective(
44
$filter
5+
, $compile
6+
, $rootScope
57
, gettext
68
, DeviceColumnService
79
, GroupService
8-
, $rootScope
10+
, DeviceService
911
, LightboxImageService
1012
, StandaloneService
1113
) {
@@ -277,6 +279,20 @@ module.exports = function DeviceListDetailsDirective(
277279
}
278280
})()
279281

282+
// check if new column needs a new scope or not
283+
// and build accordingly
284+
function buildColumn(col, device) {
285+
var td
286+
287+
if (col.scopeRequired) {
288+
var childScope = scope.$new()
289+
childScope.device = device
290+
td = col.build(childScope)
291+
} else {
292+
td = col.build()
293+
}
294+
return td
295+
}
280296
// Creates a completely new row for the device. Means that this is
281297
// the first time we see the device.
282298
function createRow(device) {
@@ -291,8 +307,10 @@ module.exports = function DeviceListDetailsDirective(
291307
}
292308

293309
for (var i = 0, l = activeColumns.length; i < l; ++i) {
294-
td = scope.columnDefinitions[activeColumns[i]].build()
295-
scope.columnDefinitions[activeColumns[i]].update(td, device)
310+
var col = scope.columnDefinitions[activeColumns[i]]
311+
312+
td = buildColumn(col, device)
313+
col.update(td, device)
296314
tr.appendChild(td)
297315
}
298316

@@ -301,6 +319,10 @@ module.exports = function DeviceListDetailsDirective(
301319
return tr
302320
}
303321

322+
scope.updateNote = function(serial, note) {
323+
DeviceService.updateNote(serial, note)
324+
}
325+
304326
// Patches all rows.
305327
function patchAll(patch) {
306328
for (var i = 0, l = rows.length; i < l; ++i) {
@@ -317,7 +339,7 @@ module.exports = function DeviceListDetailsDirective(
317339
switch (op[0]) {
318340
case 'insert':
319341
var col = scope.columnDefinitions[op[2]]
320-
tr.insertBefore(col.update(col.build(), device), tr.cells[op[1]])
342+
tr.insertBefore(col.update(buildColumn(col, device), device), tr.cells[op[1]])
321343
break
322344
case 'remove':
323345
tr.deleteCell(op[1])

res/app/device-list/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require('./device-list.css')
22

33
module.exports = angular.module('device-list', [
4+
require('angular-xeditable').name,
45
require('stf/device').name,
56
require('stf/user/group').name,
67
require('stf/control').name,
@@ -21,4 +22,8 @@ module.exports = angular.module('device-list', [
2122
controller: 'DeviceListCtrl'
2223
})
2324
}])
25+
.run(function(editableOptions) {
26+
// bootstrap3 theme for xeditables
27+
editableOptions.theme = 'bs3'
28+
})
2429
.controller('DeviceListCtrl', require('./device-list-controller'))
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require('angular-xeditable/dist/js/xeditable.js')
2+
require('angular-xeditable/dist/css/xeditable.css')
3+
require('./style.css')
4+
5+
module.exports = {
6+
name: 'xeditable'
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
a.editable-click {
2+
text-decoration: none;
3+
color: #167FFC;
4+
border-bottom: none;
5+
}
6+
7+
a.editable-click:hover {
8+
color: #808080;
9+
}
10+
11+
a.editable-empty {
12+
color: transparent;
13+
}
14+
15+
a.editable-empty:focus {
16+
color: #808080;
17+
}

0 commit comments

Comments
 (0)