mirror of
https://github.com/openstf/stf
synced 2025-10-06 03:50:04 +02:00
Refactored all device list components to its own module.
This commit is contained in:
parent
6caf3217be
commit
208094a254
31 changed files with 180 additions and 159 deletions
581
res/app/device-list/column/device-column-service.js
Normal file
581
res/app/device-list/column/device-column-service.js
Normal file
|
@ -0,0 +1,581 @@
|
|||
var _ = require('lodash')
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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: DeviceNameCell({
|
||||
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
|
||||
}
|
||||
})
|
||||
, browser: DeviceBrowserCell({
|
||||
title: gettext('Browser')
|
||||
, value: function(device) {
|
||||
return device.browser || {apps: []}
|
||||
}
|
||||
})
|
||||
, 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')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.phone ? device.phone.phoneNumber : ''
|
||||
}
|
||||
})
|
||||
, imei: TextCell({
|
||||
title: gettext('Phone IMEI')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.phone ? device.phone.imei : ''
|
||||
}
|
||||
})
|
||||
, iccid: TextCell({
|
||||
title: gettext('Phone ICCID')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.phone ? device.phone.iccid : ''
|
||||
}
|
||||
})
|
||||
, batteryHealth: TextCell({
|
||||
title: gettext('Battery Health')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.battery
|
||||
? $filter('translate')(device.enhancedBatteryHealth)
|
||||
: ''
|
||||
}
|
||||
})
|
||||
, batterySource: TextCell({
|
||||
title: gettext('Battery Source')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.battery
|
||||
? $filter('translate')(device.enhancedBatterySource)
|
||||
: ''
|
||||
}
|
||||
})
|
||||
, batteryStatus: TextCell({
|
||||
title: gettext('Battery Status')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.battery
|
||||
? $filter('translate')(device.enhancedBatteryStatus)
|
||||
: ''
|
||||
}
|
||||
})
|
||||
, batteryLevel: TextCell({
|
||||
title: gettext('Battery Level')
|
||||
, admin: true
|
||||
, value: function(device) {
|
||||
return device.battery
|
||||
? Math.floor(device.battery.level / device.battery.scale * 100) + '%'
|
||||
: ''
|
||||
}
|
||||
})
|
||||
, batteryTemp: TextCell({
|
||||
title: gettext('Battery Temp')
|
||||
, admin: true
|
||||
, 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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
function TextCell(options) {
|
||||
return _.defaults(options, {
|
||||
title: options.title
|
||||
, admin: options.admin
|
||||
, 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 DeviceBrowserCell(options) {
|
||||
return _.defaults(options, {
|
||||
title: options.title
|
||||
, defaultOrder: 'asc'
|
||||
, build: function() {
|
||||
var td = document.createElement('td')
|
||||
, span = document.createElement('span')
|
||||
span.className = 'device-browser-list'
|
||||
td.appendChild(span)
|
||||
return td
|
||||
}
|
||||
, update: function(td, device) {
|
||||
var span = td.firstChild
|
||||
, browser = options.value(device)
|
||||
|
||||
for (var i = 0, l = browser.apps.length; i < l; ++i) {
|
||||
var app = browser.apps[i]
|
||||
, img = span.childNodes[i] || span.appendChild(document.createElement('img'))
|
||||
, src = '/static/app/browsers/icon/24x24/' + (app.type || '_default') + '.png'
|
||||
|
||||
// Only change if necessary so that we don't trigger a download
|
||||
if (img.getAttribute('src') !== src) {
|
||||
img.setAttribute('src', src)
|
||||
}
|
||||
|
||||
img.title = app.name + ' (' + app.developer + ')'
|
||||
}
|
||||
|
||||
while (span.childNodes.length > browser.apps.length) {
|
||||
span.removeChild(span.lastChild)
|
||||
}
|
||||
|
||||
return td
|
||||
}
|
||||
, compare: function(a, b) {
|
||||
return options.value(a).apps.length - options.value(b).apps.length
|
||||
}
|
||||
, filter: function(device, filter) {
|
||||
return options.value(device).apps.some(function(app) {
|
||||
return filterIgnoreCase(app.type, 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')
|
||||
span.className = 'device-small-image'
|
||||
image.className = 'device-small-image-img pointer'
|
||||
span.appendChild(image)
|
||||
td.appendChild(span)
|
||||
td.appendChild(document.createTextNode(''))
|
||||
return td
|
||||
}
|
||||
, update: function(td, device) {
|
||||
var span = td.firstChild
|
||||
, image = span.firstChild
|
||||
, t = span.nextSibling
|
||||
, 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)
|
||||
}
|
||||
|
||||
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 DeviceNameCell(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
|
||||
|
||||
if (device.using) {
|
||||
a.className = 'device-product-name-using'
|
||||
a.href = '#!/control/' + device.serial
|
||||
}
|
||||
else if (device.usable) {
|
||||
a.className = 'device-product-name-usable'
|
||||
a.href = '#!/control/' + device.serial
|
||||
}
|
||||
else {
|
||||
a.className = 'device-product-name-unusable'
|
||||
a.removeAttribute('href')
|
||||
}
|
||||
|
||||
t.nodeValue = options.value(device)
|
||||
|
||||
return td
|
||||
}
|
||||
, compare: function(a, b) {
|
||||
return compareIgnoreCase(options.value(a), options.value(b))
|
||||
}
|
||||
, filter: function(device, filter) {
|
||||
return filterIgnoreCase(options.value(device), filter.query)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function DeviceStatusCell(options) {
|
||||
var stateClasses = {
|
||||
using: 'state-using btn-primary'
|
||||
, busy: 'state-busy btn-warning'
|
||||
, available: 'state-available btn-primary-outline'
|
||||
, ready: 'state-ready btn-primary-outline'
|
||||
, present: 'state-present btn-primary-outline'
|
||||
, preparing: 'state-preparing btn-primary-outline btn-success-outline'
|
||||
, unauthorized: 'state-unauthorized btn-danger-outline'
|
||||
, offline: 'state-offline btn-warning-outline'
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
a.className = 'btn btn-xs device-status ' +
|
||||
(stateClasses[device.state] || 'btn-default-outline')
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue