1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-05 02:29:26 +02:00
OpenSTF/res/app/device-list/device-column-service.js

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
}
})
}