1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-05 10:39:25 +02:00

Separate device logs

This commit is contained in:
Lukasz.Zeglinski 2019-09-11 11:04:49 +02:00
parent 345ba4d8a8
commit d99a6e7a97
29 changed files with 17057 additions and 64 deletions

View file

@ -154,6 +154,7 @@ dbapi.saveDeviceInitialState = function(serial, device) {
, remoteConnect: false , remoteConnect: false
, remoteConnectUrl: null , remoteConnectUrl: null
, usage: null , usage: null
, logs_enabled: false
} }
return db.run(r.table('devices').get(serial).update(data)) return db.run(r.table('devices').get(serial).update(data))
.then(function(stats) { .then(function(stats) {
@ -224,6 +225,7 @@ dbapi.unsetDeviceUsage = function(serial) {
return db.run(r.table('devices').get(serial).update({ return db.run(r.table('devices').get(serial).update({
usage: null usage: null
, usageChangedAt: r.now() , usageChangedAt: r.now()
, logs_enabled: false
})) }))
} }

View file

@ -43,6 +43,7 @@ module.exports = {
) )
} }
} }
, logs_enabled: false
, present: null , present: null
, providerChannel: { , providerChannel: {
indexFunction: function(device) { indexFunction: function(device) {

16472
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -50,6 +50,7 @@
"eventemitter3": "^1.2.0", "eventemitter3": "^1.2.0",
"express": "^4.14.0", "express": "^4.14.0",
"express-validator": "^2.20.8", "express-validator": "^2.20.8",
"file-saver": "1.3.3",
"formidable": "^1.2.0", "formidable": "^1.2.0",
"gm": "^1.23.0", "gm": "^1.23.0",
"hipchatter": "^0.3.1", "hipchatter": "^0.3.1",

View file

@ -6,6 +6,10 @@
padding-left: 5px; padding-left: 5px;
} }
.stf-modal .bold {
font-weight: bold;
}
.stf-modal .modal-body { .stf-modal .modal-body {
background: #fff; background: #fff;
} }

View file

@ -2,5 +2,6 @@ module.exports = angular.module('stf.modals', [
require('./fatal-message').name, require('./fatal-message').name,
require('./socket-disconnected').name, require('./socket-disconnected').name,
require('./version-update').name, require('./version-update').name,
require('./add-adb-key-modal').name require('./add-adb-key-modal').name,
require('./save-log-modal').name
]) ])

View file

@ -0,0 +1,9 @@
require('./save-log.css')
require('angular-route')
module.exports = angular.module('stf.save-log-message', [
require('stf/common-ui/modals/common').name,
'ngRoute'
])
.factory('SaveLogService', require('./save-log-service'))

View file

@ -0,0 +1,139 @@
var FileSaver = require('file-saver')
module.exports =
function SaveLogsServiceFactory($uibModal, $location, $route) {
var SaveLogService = {}
var logExtentension = ['json', 'log']
var selectedExtension = logExtentension[0]
function parseLogsToDefinedExtenstion(device, logExtension, lineLimitation) {
var lineLimiter = ((isNaN(lineLimitation)) ? device.length : lineLimitation)
var output = ''
if (device.length > 0) {
if (logExtension === 'log') {
for (let line = 0; line < lineLimiter; line++) {
output += [device[line].date, device[line].pid,
device[line].tag, device[line].priorityLabel,
device[line].message].join('\t') + '\n'
}
} else {
output = {'deviceOS': device[0].deviceLabel,
'serial': device[0].serial,
'logs': []}
for (let line = 0; line < lineLimiter; line++) {
output.logs.push({'date': device[line].date,
'pid': device[line].pid,
'tag': device[line].tag,
'priorityLabel': device[line].priorityLabel,
'message': device[line].message})
}
}
}
return output
}
function createSamplePresentation(device, logExtension, scope) {
var toSave = parseLogsToDefinedExtenstion(device,
logExtension, 4)
if (toSave.length > 0 || typeof toSave === 'object') {
switch(logExtension) {
case 'json':
scope.samplePresentation = JSON.stringify(toSave)
break
case 'log':
scope.samplePresentation = toSave
break
default:
scope.samplePresentation = toSave
break
}
}
}
var ModalInstanceCtrl = function($scope, $uibModalInstance, device) {
$scope.ok = function() {
$uibModalInstance.close(true)
$route.reload()
}
$scope.logExtentension = logExtentension
$scope.selectedExtension = $scope.logExtentension[0]
createSamplePresentation(device, $scope.selectedExtension, $scope)
$scope.second = function() {
$uibModalInstance.dismiss()
$location.path('/devices/')
}
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel')
}
$scope.saveLogs = function() {
var parsedOutput = NaN
switch(selectedExtension) {
case 'json':
parsedOutput = new Blob(
[JSON.stringify(parseLogsToDefinedExtenstion(device, selectedExtension))],
{type: 'application/json;charset=utf-8'})
break
case 'log':
parsedOutput = new Blob(
[parseLogsToDefinedExtenstion(device, selectedExtension)],
{type: 'text/plain;charset=utf-8'})
break
default:
// ToDo
// Add support for other types
// Ad-hoc save file as plain text
parsedOutput = new Blob(
[parseLogsToDefinedExtenstion(device, selectedExtension)],
{type: 'text/plain;charset=utf-8'})
break
}
if (typeof $scope.saveLogFileName === 'undefined' ||
$scope.saveLogFileName.length === 0) {
FileSaver.saveAs(parsedOutput,
(window.location.href).split('/').pop() + '_logs.' + selectedExtension)
}
else {
FileSaver.saveAs(parsedOutput,
$scope.saveLogFileName + '.' + selectedExtension)
}
$uibModalInstance.dismiss('cancel')
}
$scope.$watch('selectedExtension', function(newValue, oldValue) {
if (newValue !== oldValue) {
selectedExtension = newValue
createSamplePresentation(device, newValue, $scope)
}
})
}
SaveLogService.open = function(device, tryToReconnect) {
var modalInstance = $uibModal.open({
template: require('./save-log.pug'),
controller: ModalInstanceCtrl,
resolve: {
device: function() {
return device
},
tryToReconnect: function() {
return tryToReconnect
}
}
})
modalInstance.result.then(function() {
}, function() {
})
}
return SaveLogService
}

View file

@ -0,0 +1,11 @@
describe('SaveLogService', function() {
beforeEach(angular.mock.module(require('./').name))
it('should ...', inject(function() {
//expect(SaveLogService.doSomething()).toEqual('something');
}))
})

View file

@ -0,0 +1,9 @@
.save-log-textarea {
resize: none;
cursor: text;
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
font-size: 12px;
width: 100%;
}

View file

@ -0,0 +1,32 @@
.stf-save-log-message.stf-modal
.modal-header.dialog-header-errorX
button(type='button', ng-click='cancel()').close &times;
h4.modal-title.text-danger
i.fa.fa-save
.button-spacer
span(translate) Save Logs
.modal-body
table.table(ng-show='true')
tr.additional-modal
td(width='50%')
input(ng-model='saveLogFileName', type='text', placeholder='{{"File Name"|translate}}').input-sm.form-control
td(width='1%')
span .
td(width='20%')
select(ng-model='selectedExtension', data-ng-options='l for l in logExtentension')
tr.additional-modal
tr.additional-modal
td(width='100%')
h5.modal-title.bold
span(translate) Sample of log format
tr.additional-modal
td(width='50%', height='30%')
textarea(ng-model='samplePresentation', type='text', placeholder='...', rows="4", readonly="readonly").save-log-textarea
td(width="5%", colspan="2")
i.fa.fa-file-text-o.fa-5x
.modal-footer
button(ng-click='saveLogs()', ng-disabled='false', title='{{"Save Logs"|translate}}').btn.btn-xs.btn-danger-outline
i.fa.fa-save
span(translate) Save Logs

View file

@ -99,6 +99,13 @@
margin-top: 0; margin-top: 0;
} }
tr.additional-modal, td.additional-modal {
border-top: 10px solid;
border-top-color: transparent;
border-bottom: 1px solid;
border-bottom-color: transparent;
}
@media only screen and (max-width: 800px) { @media only screen and (max-width: 800px) {
.ng-table-responsive { .ng-table-responsive {
border-bottom: 1px solid #999999; border-bottom: 1px solid #999999;

View file

@ -1,7 +1,7 @@
var _ = require('lodash') var _ = require('lodash')
module.exports = module.exports =
function logcatTableDirective($rootScope, $timeout, LogcatService) { function logcatTableDirective($rootScope, $timeout, LogcatService, SaveLogService) {
return { return {
restrict: 'E', restrict: 'E',
replace: true, replace: true,
@ -14,28 +14,67 @@ module.exports =
var parent = element[0] var parent = element[0]
var body = element.find('tbody')[0] var body = element.find('tbody')[0]
var maxEntriesBuffer = 3000 var maxEntriesBuffer = 3000
var numberOfEntries = 0 var maxVisibleEntries = 100
var deviceSerial = (window.location.href).split('/').pop()
function incrementNumberEntry() { scope.started = checkLoggerServiceStatus(true)
numberOfEntries++ scope.allowClean = checkAllowClean()
if (numberOfEntries > maxEntriesBuffer) {
scope.clearTable() function checkAllowClean() {
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
return LogcatService.deviceEntries[deviceSerial].allowClean
}
return false
}
function checkLoggerServiceStatus(loadLogs = false) {
var collectedLogs = []
var isStarted = false
if (Object.keys($rootScope).includes('LogcatService')) {
LogcatService.deviceEntries = $rootScope.LogcatService.deviceEntries
}
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
collectedLogs = LogcatService.deviceEntries[deviceSerial].logs
isStarted = LogcatService.deviceEntries[deviceSerial].started
}
if (loadLogs) {
restoreLogs(collectedLogs)
}
return isStarted
}
function limitVisibleEntries() {
var limiter = ''
if (maxVisibleEntries > maxEntriesBuffer) {
limiter = maxEntriesBuffer
} else {
limiter = maxVisibleEntries
}
if (element.find('tbody')[0].rows.length > limiter) {
removeFirstLogTableEntry()
} }
} }
function removeFirstLogTableEntry() {
element.find('tbody')[0].deleteRow(0)
}
LogcatService.addEntryListener = function(entry) { LogcatService.addEntryListener = function(entry) {
incrementNumberEntry() if (deviceSerial === entry.serial) {
addRow(body, entry) limitVisibleEntries()
if (LogcatService.deviceEntries[deviceSerial].logs.length > maxEntriesBuffer) {
LogcatService.deviceEntries[deviceSerial].logs.shift()
}
addRow(body, entry)
}
} }
LogcatService.addFilteredEntriesListener = function(entries) { LogcatService.addFilteredEntriesListener = function(entries) {
clearTable() checkLoggerServiceStatus()
//var fragment = document.createDocumentFragment()
_.each(entries, function(entry) {
// TODO: This is not adding all the entries after first scope creation
incrementNumberEntry()
addRow(body, entry, true)
})
} }
function shouldAutoScroll() { function shouldAutoScroll() {
@ -65,11 +104,6 @@ module.exports =
var newRow = rowParent.insertRow(-1) var newRow = rowParent.insertRow(-1)
newRow.classList.add('log-' + data.priorityLabel) newRow.classList.add('log-' + data.priorityLabel)
//newRow.insertCell(-1)
// .appendChild(document.createTextNode(LogcatService.numberOfEntries))
//newRow.insertCell(-1)
// .appendChild(document.createTextNode(data.deviceLabel))
newRow.insertCell(-1) newRow.insertCell(-1)
.appendChild(document.createTextNode(data.priorityLabel)) .appendChild(document.createTextNode(data.priorityLabel))
newRow.insertCell(-1) newRow.insertCell(-1)
@ -79,8 +113,6 @@ module.exports =
.appendChild(document.createTextNode(data.pid)) .appendChild(document.createTextNode(data.pid))
newRow.insertCell(-1) newRow.insertCell(-1)
.appendChild(document.createTextNode(data.tid)) .appendChild(document.createTextNode(data.tid))
//newRow.insertCell(-1)
// .appendChild(document.createTextNode(data.app))
newRow.insertCell(-1) newRow.insertCell(-1)
.appendChild(document.createTextNode(data.tag)) .appendChild(document.createTextNode(data.tag))
} }
@ -101,10 +133,74 @@ module.exports =
scope.clearTable = function() { scope.clearTable = function() {
LogcatService.clear() LogcatService.clear()
numberOfEntries = 0
clearTable() clearTable()
} }
function restoreLogs(collectedLogs) {
clearTable()
var startFrom = 0
if (collectedLogs.length - maxVisibleEntries >= 0) {
startFrom = collectedLogs.length - maxVisibleEntries
}
for (var logLine = startFrom; logLine < collectedLogs.length; logLine++) {
if (deviceSerial === collectedLogs[logLine].serial) {
addRow(body, collectedLogs[logLine], true)
}
}
}
/**
* Validate filter.data object value and assign bordercolor to red if value
* doesn't match regex(pattern):
* - HH:mm:ss.SSS
* - H:mm:ss.SSS
* - :mm:SS.SSS
* - mm:ss.SSS
* - m:ss.SSS
* -... combinations
* in other case colour will be set to default.
*
* @param {event} event object
* @returns {None} NaN
*/
scope.validateDate = function(e) {
var pattern = ['^(?:(?:([0-1]?\\d|2[0-3]):)?(:[0-5]\\d|[0-5]\\d):|\\d)',
'?(:[0-5]\\d|[0-5]\\d{1,2})?(\\.[0-9]?\\d{0,2}|:[0-5]?\\d{0,1})|(\\d{0,2})'].join([])
var regex = new RegExp(pattern, 'g')
var inputValue = event.srcElement.value
var matchArray = inputValue.match(regex)
var isTextValid = false
if (matchArray) {
matchArray.forEach(function(item, index) {
if (item === inputValue) {
isTextValid = true
event.srcElement.style.borderColor = ''
}
})
}
if (isTextValid === false) {
event.srcElement.style.borderColor = 'red'
}
}
/**
* Show "Save Log" modal.
*
* @returns {None} NaN
*/
scope.saveLogs = function() {
var collectedLogs = []
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
collectedLogs = LogcatService.deviceEntries[deviceSerial].logs
}
SaveLogService.open(collectedLogs, false)
}
scope.$on('$destroy', function() { scope.$on('$destroy', function() {
parent.removeEventListener('scroll', throttledScrollListener) parent.removeEventListener('scroll', throttledScrollListener)
}) })

View file

@ -4,7 +4,6 @@ var _s = require('underscore.string')
module.exports = function LogcatServiceFactory(socket, FilterStringService) { module.exports = function LogcatServiceFactory(socket, FilterStringService) {
var service = {} var service = {}
service.started = false service.started = false
service.numberOfEntries = 0
service.serverFilters = [ service.serverFilters = [
{ {
@ -14,7 +13,6 @@ module.exports = function LogcatServiceFactory(socket, FilterStringService) {
] ]
service.filters = { service.filters = {
numberOfEntries: 0,
entries: [ entries: [
], ],
levelNumbers: [] levelNumbers: []
@ -48,8 +46,9 @@ module.exports = function LogcatServiceFactory(socket, FilterStringService) {
'priority' 'priority'
]) ])
service.entries = [ service.deviceSerial = []
]
service.deviceEntries = {}
service.logLevels = [ service.logLevels = [
'UNKNOWN', 'UNKNOWN',
@ -90,24 +89,56 @@ module.exports = function LogcatServiceFactory(socket, FilterStringService) {
return data return data
} }
function deviceSerialExist(serial) {
if (service.deviceSerial !== serial) {
service.deviceSerial.push(serial)
}
}
service.initDeviceLogCollector = function(serial) {
service.deviceEntries[serial] = {
logs: [], selectedLogLevel: 2, started: false, allowClean: false, filters: {
'levelNumber': service.filters.levelNumbers,
'message': '',
'pid': '',
'tid': '',
'dateLabel': '',
'date': '',
'tag': ''
}
}
}
socket.on('logcat.entry', function(rawData) { socket.on('logcat.entry', function(rawData) {
service.numberOfEntries++ deviceSerialExist(rawData.serial)
service.entries.push(enhanceEntry(rawData)) var TmpObject = enhanceEntry(rawData)
if (!Object.keys(service.deviceEntries).includes(rawData.serial)) {
service.deviceEntries[rawData.serial] = {logs: [], selectedLogLevel: 2, started: true}
}
service.deviceEntries[rawData.serial].logs.push(enhanceEntry(TmpObject))
if (typeof (service.addEntryListener) === 'function') { if (typeof (service.addEntryListener) === 'function') {
if (filterLine(rawData)) { if (filterLine(rawData)) {
rawData.logsSerial = service.deviceSerial
service.addEntryListener(rawData) service.addEntryListener(rawData)
} }
} }
}) })
service.clear = function() { service.clear = function() {
service.numberOfEntries = 0 var devSerial = (window.location.href).split('/').pop()
service.entries = [] if (Object.keys(service.deviceEntries).includes(devSerial)) {
service.deviceEntries[devSerial].logs = []
}
} }
service.filters.filterLines = function() { service.filters.filterLines = function() {
service.filters.entries = _.filter(service.entries, filterLine) var devSerial = (window.location.href).split('/').pop()
if (Object.keys(service.deviceEntries).includes(devSerial)) {
service.filters.entries = _.filter(service.deviceEntries[devSerial].logs.entries, filterLine)
}
if (typeof (service.addFilteredEntriesListener) === 'function') { if (typeof (service.addFilteredEntriesListener) === 'function') {
service.addFilteredEntriesListener(service.filters.entries) service.addFilteredEntriesListener(service.filters.entries)
@ -115,13 +146,14 @@ module.exports = function LogcatServiceFactory(socket, FilterStringService) {
} }
function filterLine(line) { function filterLine(line) {
var enabled = true
var filters = service.filters
var matched = true var matched = true
if (enabled) { var devSerial = line.serial
if (!_.isEmpty(filters.priority)) { var filters = service.deviceEntries[devSerial].filters
matched &= line.priority >= filters.priority.number
if (typeof filters !== 'undefined') {
if (!_.isEmpty(filters.priority.toString())) {
matched &= line.priority >= filters.priority
} }
if (!_.isEmpty(filters.date)) { if (!_.isEmpty(filters.date)) {
matched &= FilterStringService.filterString(filters.date, line.dateLabel) matched &= FilterStringService.filterString(filters.date, line.dateLabel)
@ -138,12 +170,9 @@ module.exports = function LogcatServiceFactory(socket, FilterStringService) {
if (!_.isEmpty(filters.message)) { if (!_.isEmpty(filters.message)) {
matched &= FilterStringService.filterString(filters.message, line.message) matched &= FilterStringService.filterString(filters.message, line.message)
} }
} else {
matched = true
} }
return matched return matched
} }
return service return service
} }

View file

@ -1,7 +1,7 @@
var _ = require('lodash') var _ = require('lodash')
module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService, module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService,
$location, $timeout, $window, $rootScope) { $location, $timeout, $window, $rootScope, LogcatService) {
$scope.showScreen = true $scope.showScreen = true
@ -9,7 +9,18 @@ module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService,
$scope.groupDevices = $scope.groupTracker.devices $scope.groupDevices = $scope.groupTracker.devices
$scope.$on('$locationChangeStart', function(event, next, current) {
$scope.LogcatService = LogcatService
$rootScope.LogcatService = LogcatService
})
$scope.kickDevice = function(device) { $scope.kickDevice = function(device) {
if (Object.keys(LogcatService.deviceEntries).includes(device.serial)) {
LogcatService.deviceEntries[device.serial].allowClean = true
}
$scope.LogcatService = LogcatService
$rootScope.LogcatService = LogcatService
if (!device || !$scope.device) { if (!device || !$scope.device) {
alert('No device found') alert('No device found')

View file

@ -1,20 +1,101 @@
module.exports = function LogsCtrl($scope, LogcatService) { module.exports = function LogsCtrl($scope, $rootScope, $routeParams, LogcatService) {
$scope.started = LogcatService.started var deviceSerial = $routeParams.serial
var cleanDevice = (window.location.href).split('/').pop()
cleanDeviceSettings()
$scope.started = checkLogBtnStatus() === null ? false : checkLogBtnStatus()
$scope.filters = {} $scope.filters = {}
$scope.filters.levelNumbers = LogcatService.filters.levelNumbers $scope.filters.levelNumbers = LogcatService.filters.levelNumbers
LogcatService.filters.filterLines() LogcatService.filters.filterLines()
restoreFilters()
setFiltersPriority()
function cleanDeviceSettings() {
if (Object.keys($rootScope).includes('LogcatService')) {
LogcatService.deviceEntries = $rootScope.LogcatService.deviceEntries
}
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
if (LogcatService.deviceEntries[deviceSerial].allowClean) {
delete LogcatService.deviceEntries[deviceSerial]
if ($scope.control !== null) {
$scope.control.stopLogcat()
}
}
}
}
function setFiltersPriority() {
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
$scope.filters.priority = $scope.filters.levelNumbers[
LogcatService.deviceEntries[deviceSerial].selectedLogLevel - 2]
} else {
if ($scope.started) {
$scope.filters.priority = $scope.filters.levelNumbers[0]
}
}
}
function restoreFilters() {
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
Object.keys(LogcatService.deviceEntries[deviceSerial].filters).forEach(function(entry) {
if ('filter.' + entry !== 'filter.priority') {
$scope.filters[entry] = LogcatService.deviceEntries[deviceSerial].filters[entry]
} else {
setFiltersPriority()
}
})
}
}
function checkLogBtnStatus() {
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
if ($scope !== null && $scope.device !== null) {
if($scope.device.logs_enabled && LogcatService.deviceEntries[deviceSerial].started) {
return LogcatService.deviceEntries[deviceSerial].started
}
}
}
return null
}
$scope.$watch('started', function(newValue, oldValue) { $scope.$watch('started', function(newValue, oldValue) {
if (!Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
LogcatService.deviceEntries[deviceSerial] = {logs: [], selectedLogLevel: 2, started: false,
filters: {
'message': '',
'pid': '',
'tid': '',
'dateLabel': '',
'date': '',
'tag': '',
'priority': '',
}
}
}
if (newValue !== oldValue) { if (newValue !== oldValue) {
LogcatService.started = newValue LogcatService.deviceEntries[deviceSerial].started = newValue
if (newValue) {
if (LogcatService.deviceEntries[deviceSerial].started) {
$scope.control.startLogcat([]).then(function() { $scope.control.startLogcat([]).then(function() {
}) })
LogcatService.deviceEntries[deviceSerial].started = true
$scope.device.logs_enabled = true
setFiltersPriority()
} else { } else {
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
LogcatService.deviceEntries[deviceSerial].started = false
}
LogcatService.deviceEntries[deviceSerial].started = false
$scope.device.logs_enabled = false
$scope.control.stopLogcat() $scope.control.stopLogcat()
} }
} }
@ -22,19 +103,79 @@ module.exports = function LogsCtrl($scope, LogcatService) {
window.onbeforeunload = function() { window.onbeforeunload = function() {
if ($scope.control) { if ($scope.control) {
for(var i = 0; i < LogcatService.deviceEntries.length; i++) {
if(LogcatService.deviceEntries[i] === deviceSerial) {
LogcatService.deviceEntries.splice(i, 1)
}
}
LogcatService.deviceEntries[deviceSerial].started = false
$scope.control.stopLogcat() $scope.control.stopLogcat()
} }
} }
$scope.clear = function() { $scope.clear = function() {
LogcatService.clear() var deviceSerial = (window.location.href).split('/').pop()
if (Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
for (var i = LogcatService.deviceSerial.length - 1; i >= 0; i++) {
if (LogcatService.deviceSerial[i] === deviceSerial) {
LogcatService.deviceSerial.splice(i, 1)
}
}
}
} }
function defineFilterWatchers(props) { function defineFilterWatchers(props) {
angular.forEach(props, function(prop) { angular.forEach(props, function(prop) {
$scope.$watch('filters.' + prop, function(newValue, oldValue) { $scope.$watch('filters.' + prop, function(newValue, oldValue) {
if (!angular.equals(newValue, oldValue)) { if (!angular.equals(newValue, oldValue)) {
var deviceSerial = (window.location.href).split('/').pop()
LogcatService.filters[prop] = newValue LogcatService.filters[prop] = newValue
if (!Object.keys(LogcatService.deviceEntries).includes(deviceSerial)) {
LogcatService.initDeviceLogCollector(deviceSerial)
}
var transformedInput = ''
switch('filters.' + prop) {
case 'filters.priority':
case 'filters.levelNumber':
if (newValue !== null && !isNaN(newValue.number)) {
LogcatService.deviceEntries[deviceSerial].selectedLogLevel = newValue.number
$scope.filters.priority = $scope.filters.levelNumbers[
LogcatService.deviceEntries[deviceSerial].selectedLogLevel - 2]
transformedInput = LogcatService.deviceEntries[deviceSerial].selectedLogLevel
}
break
case 'filters.pid':
transformedInput = newValue.replace(/[^0-9:]/g, '')
if (transformedInput !== newValue) {
$scope.filters.pid = transformedInput
}
break
case 'filters.tid':
transformedInput = newValue.replace(/[^0-9]/g, '')
if (transformedInput !== newValue) {
$scope.filters.tid = transformedInput
}
break
default:
transformedInput = newValue
}
// Exclude Debug Level info
if (prop !== 'levelNumber') {
LogcatService.deviceEntries[deviceSerial].filters[prop] = transformedInput
}
LogcatService.filters[prop] = transformedInput
// Check if scope is defined
if ($scope !== 'undefined') {
setFiltersPriority()
}
LogcatService.deviceEntries[deviceSerial].allowClean = false
LogcatService.allowClean = false
} }
}) })
}) })

View file

@ -6,6 +6,9 @@ describe('LogsCtrl', function() {
beforeEach(inject(function($rootScope, $controller) { beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new() scope = $rootScope.$new()
if (Object.keys($rootScope.LogcatService).length > 0) {
scope.deviceEntries = $rootScope.LogcatService
}
ctrl = $controller('LogsCtrl', {$scope: scope}) ctrl = $controller('LogsCtrl', {$scope: scope})
})) }))

View file

@ -9,10 +9,10 @@
span(ng-if='started') {{"Stop"|translate}} span(ng-if='started') {{"Stop"|translate}}
span(ng-if='!started') {{"Get"|translate}} span(ng-if='!started') {{"Get"|translate}}
td(width='6%') td(width='6%')
select(ng-model='filters.priority', ng-options='l.name for l in filters.levelNumbers') select(ng-model='filters.priority', data-ng-options='l.name for l in filters.levelNumbers')
option(value='', disabled, selected) {{"Level"|translate}} option(value='') {{"Logcat Level"|translate}}
td(width='10%') td(width='10%')
input(ng-model='filters.date', type='text', placeholder='{{"Time"|translate}}').input-sm.form-control input(ng-model='filters.date', type='text', placeholder='{{"Time"|translate}}', ng-keyup='validateDate(event=$event)').input-sm.form-control
td(width='8%', ng-if='$root.platform == "native"') td(width='8%', ng-if='$root.platform == "native"')
input(ng-model='filters.pid', type='text', placeholder='{{"PID"|translate}}').input-sm.form-control input(ng-model='filters.pid', type='text', placeholder='{{"PID"|translate}}').input-sm.form-control
td(width='8%', ng-if='$root.platform == "native"') td(width='8%', ng-if='$root.platform == "native"')
@ -25,5 +25,9 @@
button(ng-click='clearTable()', ng-disabled='false', title='{{"Clear"|translate}}').btn.btn-xs.btn-danger-outline button(ng-click='clearTable()', ng-disabled='false', title='{{"Clear"|translate}}').btn.btn-xs.btn-danger-outline
i.fa.fa-trash-o i.fa.fa-trash-o
span(translate) Clear span(translate) Clear
td(width='0')
button(ng-click='saveLogs()', ng-disabled='false', title='{{"Save Logs"|translate}}').btn.btn-xs.btn-danger-outline
i.fa.fa-save
span(translate) Save Logs
logcat-table(add-row='lastEntry') logcat-table(add-row='lastEntry')

View file

@ -10,6 +10,7 @@ module.exports = function DeviceListDetailsDirective(
, DeviceService , DeviceService
, LightboxImageService , LightboxImageService
, StandaloneService , StandaloneService
, LogcatService
) { ) {
return { return {
restrict: 'E' restrict: 'E'
@ -34,6 +35,11 @@ module.exports = function DeviceListDetailsDirective(
function kickDevice(device, force) { function kickDevice(device, force) {
LogcatService.allowClean = true
if (Object.keys(LogcatService.deviceEntries).includes(device.serial)) {
LogcatService.deviceEntries[device.serial].allowClean = true
}
$rootScope.LogcatService = LogcatService
return GroupService.kick(device, force).catch(function(e) { return GroupService.kick(device, force).catch(function(e) {
alert($filter('translate')(gettext('Device cannot get kicked from the group'))) alert($filter('translate')(gettext('Device cannot get kicked from the group')))
throw new Error(e) throw new Error(e)
@ -41,6 +47,7 @@ module.exports = function DeviceListDetailsDirective(
} }
function inviteDevice(device) { function inviteDevice(device) {
$rootScope.usedDevices.push(device.serial)
return GroupService.invite(device).then(function() { return GroupService.invite(device).then(function() {
scope.$digest() scope.$digest()
}) })

View file

@ -6,6 +6,8 @@ module.exports = function DeviceListIconsDirective(
, DeviceColumnService , DeviceColumnService
, GroupService , GroupService
, StandaloneService , StandaloneService
, LogcatService
, $rootScope
) { ) {
function DeviceItem() { function DeviceItem() {
return { return {
@ -83,10 +85,13 @@ module.exports = function DeviceListIconsDirective(
name.classList.remove('state-available') name.classList.remove('state-available')
} }
if (device.usable) { if (device.usable && !device.using) {
a.href = '#!/control/' + device.serial a.href = '#!/control/' + device.serial
li.classList.remove('device-is-busy') li.classList.remove('device-is-busy')
} }
else if (device.using && device.usable) {
a.href = '#!/control/' + device.serial
}
else { else {
a.removeAttribute('href') a.removeAttribute('href')
li.classList.add('device-is-busy') li.classList.add('device-is-busy')
@ -119,6 +124,11 @@ module.exports = function DeviceListIconsDirective(
function kickDevice(device, force) { function kickDevice(device, force) {
if (Object.keys(LogcatService.deviceEntries).includes(device.serial)) {
LogcatService.deviceEntries[device.serial].allowClean = true
}
LogcatService.allowClean = true
$rootScope.LogcatService = LogcatService
return GroupService.kick(device, force).catch(function(e) { return GroupService.kick(device, force).catch(function(e) {
alert($filter('translate')(gettext('Device cannot get kicked from the group'))) alert($filter('translate')(gettext('Device cannot get kicked from the group')))
throw new Error(e) throw new Error(e)
@ -159,8 +169,11 @@ module.exports = function DeviceListIconsDirective(
} }
if (device.using) { if (device.using) {
kickDevice(device) if (e.target.classList.contains('btn') &&
e.preventDefault() e.target.classList.contains('state-using')) {
kickDevice(device)
e.preventDefault()
}
} }
} }
}) })

View file

@ -1,5 +1,5 @@
module.exports = function MenuCtrl($scope, $rootScope, SettingsService, module.exports = function MenuCtrl($scope, $rootScope, SettingsService,
$location) { $location, LogcatService) {
SettingsService.bind($scope, { SettingsService.bind($scope, {
target: 'lastUsedDevice' target: 'lastUsedDevice'
@ -7,7 +7,8 @@ module.exports = function MenuCtrl($scope, $rootScope, SettingsService,
SettingsService.bind($rootScope, { SettingsService.bind($rootScope, {
target: 'platform', target: 'platform',
defaultValue: 'native' defaultValue: 'native',
deviceEntries: LogcatService.deviceEntries
}) })
$scope.$on('$routeChangeSuccess', function() { $scope.$on('$routeChangeSuccess', function() {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long