mirror of
https://github.com/openstf/stf
synced 2025-10-05 02:29:26 +02:00
496 lines
13 KiB
JavaScript
496 lines
13 KiB
JavaScript
var _ = require('lodash')
|
|
|
|
module.exports = function DeviceColumnService($filter, gettext) {
|
|
// Definitions for all possible values.
|
|
return {
|
|
state: DeviceStatusCell({
|
|
title: gettext('Status')
|
|
, value: function(device) {
|
|
return $filter('translate')(device.enhancedStateAction)
|
|
}
|
|
})
|
|
, model: DeviceModelCell({
|
|
title: gettext('Model')
|
|
, value: function(device) {
|
|
return device.model || device.serial
|
|
}
|
|
})
|
|
, name: TextCell({
|
|
title: gettext('Product')
|
|
, value: function(device) {
|
|
return device.name || ''
|
|
}
|
|
})
|
|
, operator: TextCell({
|
|
title: gettext('Carrier')
|
|
, value: function(device) {
|
|
return device.operator || ''
|
|
}
|
|
})
|
|
, releasedAt: DateCell({
|
|
title: gettext('Released')
|
|
, value: function(device) {
|
|
return device.releasedAt ? new Date(device.releasedAt) : null
|
|
}
|
|
})
|
|
, version: TextCell({
|
|
title: gettext('OS')
|
|
, value: function(device) {
|
|
return device.version || ''
|
|
}
|
|
, compare: function(deviceA, deviceB) {
|
|
var va = (deviceA.version || '0').split('.')
|
|
, vb = (deviceB.version || '0').split('.')
|
|
, la = va.length
|
|
, lb = vb.length
|
|
|
|
for (var i = 0, l = Math.max(la, lb); i < l; ++i) {
|
|
var a = i < la ? parseInt(va[i], 10) : 0
|
|
, b = i < lb ? parseInt(vb[i], 10) : 0
|
|
, diff = a - b
|
|
|
|
if (diff !== 0) {
|
|
return diff
|
|
}
|
|
}
|
|
|
|
return 0
|
|
}
|
|
, filter: function(device, filter) {
|
|
var va = (device.version || '0').split('.')
|
|
, vb = (filter.query || '0').split('.')
|
|
, la = va.length
|
|
, lb = vb.length
|
|
, op = filterOps[filter.op || '=']
|
|
|
|
if (vb[lb - 1] === '') {
|
|
// This means that the query is not complete yet, and we're
|
|
// looking at something like "4.", which means that the last part
|
|
// should be ignored.
|
|
vb.pop()
|
|
lb -= 1
|
|
}
|
|
|
|
for (var i = 0, l = Math.min(la, lb); i < l; ++i) {
|
|
var a = parseInt(va[i], 10)
|
|
, b = parseInt(vb[i], 10)
|
|
|
|
if (!op(a, b)) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
})
|
|
, network: TextCell({
|
|
title: gettext('Network')
|
|
, value: function(device) {
|
|
return device.phone ? device.phone.network : ''
|
|
}
|
|
})
|
|
, display: TextCell({
|
|
title: gettext('Screen')
|
|
, defaultOrder: 'desc'
|
|
, value: function(device) {
|
|
return device.display && device.display.width
|
|
? device.display.width + 'x' + device.display.height
|
|
: ''
|
|
}
|
|
, compare: function(deviceA, deviceB) {
|
|
var va = deviceA.display && deviceA.display.width
|
|
? deviceA.display.width * deviceA.display.height
|
|
: 0
|
|
var vb = deviceB.display && deviceB.display.width
|
|
? deviceB.display.width * deviceB.display.height
|
|
: 0
|
|
return va - vb
|
|
}
|
|
})
|
|
, serial: TextCell({
|
|
title: gettext('Serial')
|
|
, value: function(device) {
|
|
return device.serial || ''
|
|
}
|
|
})
|
|
, manufacturer: TextCell({
|
|
title: gettext('Manufacturer')
|
|
, value: function(device) {
|
|
return device.manufacturer || ''
|
|
}
|
|
})
|
|
, sdk: NumberCell({
|
|
title: gettext('SDK')
|
|
, defaultOrder: 'desc'
|
|
, value: function(device) {
|
|
return device.sdk || ''
|
|
}
|
|
})
|
|
, abi: TextCell({
|
|
title: gettext('ABI')
|
|
, value: function(device) {
|
|
return device.abi || ''
|
|
}
|
|
})
|
|
, phone: TextCell({
|
|
title: gettext('Phone')
|
|
, value: function(device) {
|
|
return device.phone ? device.phone.phoneNumber : ''
|
|
}
|
|
})
|
|
, imei: TextCell({
|
|
title: gettext('Phone IMEI')
|
|
, value: function(device) {
|
|
return device.phone ? device.phone.imei : ''
|
|
}
|
|
})
|
|
, iccid: TextCell({
|
|
title: gettext('Phone ICCID')
|
|
, value: function(device) {
|
|
return device.phone ? device.phone.iccid : ''
|
|
}
|
|
})
|
|
, batteryHealth: TextCell({
|
|
title: gettext('Battery Health')
|
|
, value: function(device) {
|
|
return device.battery
|
|
? $filter('translate')(device.enhancedBatteryHealth)
|
|
: ''
|
|
}
|
|
})
|
|
, batterySource: TextCell({
|
|
title: gettext('Battery Source')
|
|
, value: function(device) {
|
|
return device.battery
|
|
? $filter('translate')(device.enhancedBatterySource)
|
|
: ''
|
|
}
|
|
})
|
|
, batteryStatus: TextCell({
|
|
title: gettext('Battery Status')
|
|
, value: function(device) {
|
|
return device.battery
|
|
? $filter('translate')(device.enhancedBatteryStatus)
|
|
: ''
|
|
}
|
|
})
|
|
, batteryLevel: TextCell({
|
|
title: gettext('Battery Level')
|
|
, value: function(device) {
|
|
return device.battery
|
|
? Math.floor(device.battery.level / device.battery.scale * 100) + '%'
|
|
: ''
|
|
}
|
|
})
|
|
, batteryTemp: TextCell({
|
|
title: gettext('Battery Temp')
|
|
, value: function(device) {
|
|
return device.battery ? device.battery.temp + '°C' : ''
|
|
}
|
|
})
|
|
, provider: TextCell({
|
|
title: gettext('Location')
|
|
, value: function(device) {
|
|
return device.provider ? device.provider.name : ''
|
|
}
|
|
})
|
|
, owner: LinkCell({
|
|
title: gettext('User')
|
|
, target: '_blank'
|
|
, value: function(device) {
|
|
return device.owner ? device.owner.name : ''
|
|
}
|
|
, link: function(device) {
|
|
return device.owner ? device.enhancedUserContactUrl : ''
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function zeroPadTwoDigit(digit) {
|
|
return digit < 10 ? '0' + digit : '' + digit
|
|
}
|
|
|
|
function compareIgnoreCase(a, b) {
|
|
var la = (a || '').toLowerCase()
|
|
, lb = (b || '').toLowerCase()
|
|
return la === lb ? 0 : (la < lb ? -1 : 1)
|
|
}
|
|
|
|
function filterIgnoreCase(a, filterValue) {
|
|
var va = (a || '').toLowerCase()
|
|
, vb = filterValue.toLowerCase()
|
|
return va.indexOf(vb) !== -1
|
|
}
|
|
|
|
function compareRespectCase(a, b) {
|
|
return a === b ? 0 : (a < b ? -1 : 1)
|
|
}
|
|
|
|
var filterOps = {
|
|
'<': function(a, filterValue) {
|
|
return a < filterValue
|
|
}
|
|
, '<=': function(a, filterValue) {
|
|
return a <= filterValue
|
|
}
|
|
, '>': function(a, filterValue) {
|
|
return a > filterValue
|
|
}
|
|
, '>=': function(a, filterValue) {
|
|
return a >= filterValue
|
|
}
|
|
, '=': function(a, filterValue) {
|
|
return a === filterValue
|
|
}
|
|
}
|
|
|
|
function TextCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'asc'
|
|
, build: function () {
|
|
var td = document.createElement('td')
|
|
td.appendChild(document.createTextNode(''))
|
|
return td
|
|
}
|
|
, update: function(td, item) {
|
|
var t = td.firstChild
|
|
t.nodeValue = options.value(item)
|
|
return td
|
|
}
|
|
, compare: function(a, b) {
|
|
return compareIgnoreCase(options.value(a), options.value(b))
|
|
}
|
|
, filter: function(item, filter) {
|
|
return filterIgnoreCase(options.value(item), filter.query)
|
|
}
|
|
})
|
|
}
|
|
|
|
function NumberCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'asc'
|
|
, build: function () {
|
|
var td = document.createElement('td')
|
|
td.appendChild(document.createTextNode(''))
|
|
return td
|
|
}
|
|
, update: function(td, item) {
|
|
var t = td.firstChild
|
|
t.nodeValue = options.value(item)
|
|
return td
|
|
}
|
|
, compare: function(a, b) {
|
|
return options.value(a) - options.value(b)
|
|
}
|
|
, filter: (function() {
|
|
return function(item, filter) {
|
|
return filterOps[filter.op || '='](
|
|
options.value(item)
|
|
, +filter.query
|
|
)
|
|
}
|
|
})()
|
|
})
|
|
}
|
|
|
|
function DateCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'desc'
|
|
, build: function () {
|
|
var td = document.createElement('td')
|
|
td.appendChild(document.createTextNode(''))
|
|
return td
|
|
}
|
|
, update: function(td, item) {
|
|
var t = td.firstChild
|
|
, date = options.value(item)
|
|
if (date) {
|
|
t.nodeValue = date.getFullYear()
|
|
+ '-'
|
|
+ zeroPadTwoDigit(date.getMonth() + 1)
|
|
+ '-'
|
|
+ zeroPadTwoDigit(date.getDate())
|
|
}
|
|
else {
|
|
t.nodeValue = ''
|
|
}
|
|
return td
|
|
}
|
|
, compare: function(a, b) {
|
|
var va = options.value(a) || 0
|
|
, vb = options.value(b) || 0
|
|
return va - vb
|
|
}
|
|
, filter: (function() {
|
|
function dateNumber(d) {
|
|
return d
|
|
? d.getFullYear() * 10000 + d.getMonth() * 100 + d.getDate()
|
|
: 0
|
|
}
|
|
return function(item, filter) {
|
|
var filterDate = new Date(filter.query)
|
|
, va = dateNumber(options.value(item))
|
|
, vb = dateNumber(filterDate)
|
|
return filterOps[filter.op || '='](va, vb)
|
|
}
|
|
})()
|
|
})
|
|
}
|
|
|
|
function LinkCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'asc'
|
|
, build: function () {
|
|
var td = document.createElement('td')
|
|
, a = document.createElement('a')
|
|
a.appendChild(document.createTextNode(''))
|
|
td.appendChild(a)
|
|
return td
|
|
}
|
|
, update: function(td, item) {
|
|
var a = td.firstChild
|
|
, t = a.firstChild
|
|
, href = options.link(item)
|
|
if (href) {
|
|
a.setAttribute('href', href)
|
|
}
|
|
else {
|
|
a.removeAttribute('href')
|
|
}
|
|
a.target = options.target || ''
|
|
t.nodeValue = options.value(item)
|
|
return td
|
|
}
|
|
, compare: function(a, b) {
|
|
return compareIgnoreCase(options.value(a), options.value(b))
|
|
}
|
|
, filter: function(item, filter) {
|
|
return filterIgnoreCase(options.value(item), filter.query)
|
|
}
|
|
})
|
|
}
|
|
|
|
function DeviceModelCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'asc'
|
|
, build: function() {
|
|
var td = document.createElement('td')
|
|
, span = document.createElement('span')
|
|
, image = document.createElement('img')
|
|
, a = document.createElement('a')
|
|
span.className = 'device-small-image'
|
|
span.appendChild(image)
|
|
td.appendChild(span)
|
|
a.appendChild(document.createTextNode(''))
|
|
td.appendChild(a)
|
|
return td
|
|
}
|
|
, update: function(td, device) {
|
|
var span = td.firstChild
|
|
, image = span.firstChild
|
|
, a = span.nextSibling
|
|
, t = a.firstChild
|
|
, src = '/static/app/devices/icon/x24/' +
|
|
(device.image || '_default.jpg')
|
|
// Only change if necessary so that we don't trigger a download
|
|
if (image.getAttribute('src') !== src) {
|
|
image.setAttribute('src', src)
|
|
}
|
|
|
|
if (device.using) {
|
|
a.className = 'btn btn-xs btn-primary-outline'
|
|
a.href = '#!/control/' + device.serial
|
|
}
|
|
else {
|
|
a.className = 'device-model-link-off'
|
|
a.removeAttribute('href')
|
|
}
|
|
|
|
t.nodeValue = options.value(device)
|
|
return td
|
|
}
|
|
, compare: function(a, b) {
|
|
return compareRespectCase(options.value(a), options.value(b))
|
|
}
|
|
, filter: function(device, filter) {
|
|
return filterIgnoreCase(options.value(device), filter.query)
|
|
}
|
|
})
|
|
}
|
|
|
|
function DeviceStatusCell(options) {
|
|
return _.defaults(options, {
|
|
title: options.title
|
|
, defaultOrder: 'asc'
|
|
, build: function() {
|
|
var td = document.createElement('td')
|
|
, a = document.createElement('a')
|
|
a.appendChild(document.createTextNode(''))
|
|
td.appendChild(a)
|
|
return td
|
|
}
|
|
, update: function(td, device) {
|
|
var a = td.firstChild
|
|
, t = a.firstChild
|
|
, classes = 'btn btn-xs device-status '
|
|
switch (device.state) {
|
|
case 'using':
|
|
a.className = classes + 'btn-primary'
|
|
break
|
|
case 'busy':
|
|
a.className = classes + 'btn-warning'
|
|
break
|
|
case 'available':
|
|
case 'ready':
|
|
case 'present':
|
|
a.className = classes + 'btn-primary-outline'
|
|
break
|
|
case 'preparing':
|
|
a.className = classes + 'btn-primary-outline btn-success-outline'
|
|
break
|
|
case 'unauthorized':
|
|
a.className = classes + 'btn-danger-outline'
|
|
break
|
|
case 'offline':
|
|
a.className = classes + 'btn-warning-outline'
|
|
break
|
|
default:
|
|
a.className = classes + 'btn-default-outline'
|
|
break
|
|
}
|
|
if (device.usable && !device.using) {
|
|
a.href = '#!/control/' + device.serial
|
|
}
|
|
else {
|
|
a.removeAttribute('href')
|
|
}
|
|
t.nodeValue = options.value(device)
|
|
return td
|
|
}
|
|
, compare: (function() {
|
|
var order = {
|
|
using: 10
|
|
, available: 20
|
|
, busy: 30
|
|
, ready: 40
|
|
, preparing: 50
|
|
, unauthorized: 60
|
|
, offline: 70
|
|
, present: 80
|
|
, absent: 90
|
|
}
|
|
return function(deviceA, deviceB) {
|
|
return order[deviceA.state] - order[deviceB.state]
|
|
}
|
|
})()
|
|
, filter: function(device, filter) {
|
|
return device.state === filter.query
|
|
}
|
|
})
|
|
}
|