devices in progress, UI half done...
This commit is contained in:
Родитель
b90f8ff5bb
Коммит
fc2eac072b
|
@ -72,12 +72,14 @@ return [
|
|||
'requirements' => ['path' => '.+']
|
||||
],
|
||||
['name' => 'devices_api#getDevices', 'url' => '/api/{apiversion}/devices', 'verb' => 'GET'],
|
||||
['name' => 'devices_api#getDevicePoints', 'url' => '/api/{apiversion}/devices/{id}', 'verb' => 'GET'],
|
||||
['name' => 'devices_api#addDevicePoint', 'url' => '/api/{apiversion}/devices', 'verb' => 'POST'],
|
||||
['name' => 'devices_api#editDevice', 'url' => '/api/{apiversion}/devices/{id}', 'verb' => 'PUT'],
|
||||
['name' => 'devices_api#deleteDevice', 'url' => '/api/{apiversion}/devices/{id}', 'verb' => 'DELETE'],
|
||||
|
||||
// devices
|
||||
['name' => 'devices#getDevices', 'url' => '/devices', 'verb' => 'GET'],
|
||||
['name' => 'devices#getDevicePoints', 'url' => '/devices/{id}', 'verb' => 'GET'],
|
||||
['name' => 'devices#addDevicePoint', 'url' => '/devices', 'verb' => 'POST'],
|
||||
['name' => 'devices#editDevice', 'url' => '/devices/{id}', 'verb' => 'PUT'],
|
||||
['name' => 'devices#deleteDevice', 'url' => '/devices/{id}', 'verb' => 'DELETE'],
|
||||
|
|
|
@ -6,7 +6,7 @@ function DevicesController(optionsController, timeFilterController) {
|
|||
// indexed by device id
|
||||
// those actually added to map, those which get toggled
|
||||
this.mapDeviceLayers = {};
|
||||
// layers which actually contain lines/waypoints, those which get filtered
|
||||
// layers which actually contain lines, those which get filtered
|
||||
this.deviceLayers = {};
|
||||
this.deviceColors = {};
|
||||
this.deviceDivIcon = {};
|
||||
|
@ -44,6 +44,23 @@ DevicesController.prototype = {
|
|||
var id = $(this).parent().parent().parent().attr('device');
|
||||
that.toggleDevice(id, true);
|
||||
});
|
||||
// toggle devices
|
||||
$('body').on('click', '#toggleDevicesButton', function(e) {
|
||||
that.toggleDevices();
|
||||
that.optionsController.saveOptionValues({devicesEnabled: that.map.hasLayer(that.mainLayer)});
|
||||
that.updateMyFirstLastDates();
|
||||
});
|
||||
// expand track list
|
||||
$('body').on('click', '#navigation-devices > a', function(e) {
|
||||
that.toggleDeviceList();
|
||||
that.optionsController.saveOptionValues({deviceListShow: $('#navigation-devices').hasClass('open')});
|
||||
});
|
||||
$('body').on('click', '#navigation-devices', function(e) {
|
||||
if (e.target.tagName === 'LI' && $(e.target).attr('id') === 'navigation-devices') {
|
||||
that.toggleDeviceList();
|
||||
that.optionsController.saveOptionValues({deviceListShow: $('#navigation-devices').hasClass('open')});
|
||||
}
|
||||
});
|
||||
// send my position on page load
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(function (position) {
|
||||
|
@ -55,6 +72,261 @@ DevicesController.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
// expand or fold device list in sidebar
|
||||
toggleDeviceList: function() {
|
||||
$('#navigation-devices').toggleClass('open');
|
||||
},
|
||||
|
||||
// toggle tracks general layer on map and save state in user options
|
||||
toggleDevices: function() {
|
||||
if (this.map.hasLayer(this.mainLayer)) {
|
||||
this.map.removeLayer(this.mainLayer);
|
||||
// color of the eye
|
||||
$('#toggleDevicesButton button').addClass('icon-toggle').attr('style', '');
|
||||
}
|
||||
else {
|
||||
if (!this.deviceListLoaded) {
|
||||
this.getDevices();
|
||||
}
|
||||
this.map.addLayer(this.mainLayer);
|
||||
// color of the eye
|
||||
var color = OCA.Theming.color.replace('#', '');
|
||||
var imgurl = OC.generateUrl('/svg/core/actions/toggle?color='+color);
|
||||
$('#toggleDevicesButton button').removeClass('icon-toggle').css('background-image', 'url('+imgurl+')');
|
||||
}
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
var that = this;
|
||||
$('#navigation-devices').addClass('icon-loading-small');
|
||||
var req = {};
|
||||
var url = OC.generateUrl('/apps/maps/devices');
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: url,
|
||||
data: req,
|
||||
async: true
|
||||
}).done(function (response) {
|
||||
var i, device;
|
||||
for (i=0; i < response.length; i++) {
|
||||
device = response[i];
|
||||
that.addDeviceMap(device, false, true);
|
||||
}
|
||||
that.deviceListLoaded = true;
|
||||
}).always(function (response) {
|
||||
$('#navigation-devices').removeClass('icon-loading-small');
|
||||
}).fail(function() {
|
||||
OC.Notification.showTemporary(t('maps', 'Failed to load device list'));
|
||||
});
|
||||
},
|
||||
|
||||
addDeviceMap: function(device, show=false, pageLoad=false) {
|
||||
// color
|
||||
var color = device.color || OCA.Theming.color;
|
||||
this.deviceDivIcon[device.id] = L.divIcon({
|
||||
iconAnchor: [12, 25],
|
||||
className: 'trackWaypoint trackWaypoint-'+device.id,
|
||||
html: ''
|
||||
});
|
||||
this.devices[device.id] = device;
|
||||
|
||||
this.mapDeviceLayers[device.id] = L.featureGroup();
|
||||
this.deviceLayers[device.id] = L.featureGroup();
|
||||
this.deviceLayers[device.id].loaded = false;
|
||||
this.mapDeviceLayers[device.id].addLayer(this.deviceLayers[device.id]);
|
||||
|
||||
var name = device.user_agent;
|
||||
|
||||
// side menu entry
|
||||
var imgurl = OC.generateUrl('/svg/core/clients/phone?color='+color.replace('#', ''));
|
||||
var li = '<li class="device-line" id="'+name+'-device" device="'+device.id+'" name="'+name+'">' +
|
||||
' <a href="#" class="device-name" id="'+name+'-device-name" style="background-image: url('+imgurl+')">'+name+'</a>' +
|
||||
' <div class="app-navigation-entry-utils">' +
|
||||
' <ul>' +
|
||||
' <li class="app-navigation-entry-utils-menu-button toggleDeviceButton" title="'+t('maps', 'Toggle device')+'">' +
|
||||
' <button class="icon-toggle"></button>' +
|
||||
' </li>' +
|
||||
' <li class="app-navigation-entry-utils-menu-button deviceMenuButton">' +
|
||||
' <button></button>' +
|
||||
' </li>' +
|
||||
' </ul>' +
|
||||
' </div>' +
|
||||
' <div class="app-navigation-entry-menu">' +
|
||||
' <ul>' +
|
||||
' <li>' +
|
||||
' <a href="#" class="changeDeviceColor">' +
|
||||
' <span class="icon-rename"></span>' +
|
||||
' <span>'+t('maps', 'Change device color')+'</span>' +
|
||||
' </a>' +
|
||||
' </li>' +
|
||||
' <li>' +
|
||||
' <a href="#" class="deleteDevice">' +
|
||||
' <span class="icon-delete"></span>' +
|
||||
' <span>'+t('maps', 'Delete')+'</span>' +
|
||||
' </a>' +
|
||||
' </li>' +
|
||||
' </ul>' +
|
||||
' </div>' +
|
||||
' <div class="app-navigation-entry-deleted">' +
|
||||
' <div class="app-navigation-entry-deleted-description">'+t('maps', 'Device deleted')+'</div>' +
|
||||
' <button class="app-navigation-entry-deleted-button icon-history undoDeleteDevice" title="Undo"></button>' +
|
||||
' </div>' +
|
||||
'</li>';
|
||||
|
||||
var beforeThis = null;
|
||||
var nameLower = name.toLowerCase();
|
||||
var deviceName;
|
||||
$('#device-list > li').each(function() {
|
||||
deviceName = $(this).attr('name');
|
||||
if (nameLower.localeCompare(deviceName) < 0) {
|
||||
beforeThis = $(this);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (beforeThis !== null) {
|
||||
$(li).insertBefore(beforeThis);
|
||||
}
|
||||
else {
|
||||
$('#device-list').append(li);
|
||||
}
|
||||
|
||||
// enable if in saved options or if it should be enabled for another reason
|
||||
if (show || this.optionsController.enabledDevices.indexOf(device.id) !== -1) {
|
||||
this.toggleDevice(device.id, false, pageLoad);
|
||||
}
|
||||
},
|
||||
|
||||
saveEnabledDevices: function(additionalIds=[]) {
|
||||
var deviceList = [];
|
||||
var layer;
|
||||
for (var id in this.mapDeviceLayers) {
|
||||
layer = this.mapDeviceLayers[id];
|
||||
if (this.mainLayer.hasLayer(layer)) {
|
||||
deviceList.push(id);
|
||||
}
|
||||
}
|
||||
for (var i=0; i < additionalIds.length; i++) {
|
||||
deviceList.push(additionalIds[i]);
|
||||
}
|
||||
var deviceStringList = deviceList.join('|');
|
||||
this.optionsController.saveOptionValues({enabledDevices: deviceStringList});
|
||||
// this is used when tracks are loaded again
|
||||
this.optionsController.enabledDevices = deviceList;
|
||||
},
|
||||
|
||||
restoreDevicesState: function(enabledDeviceList) {
|
||||
var id;
|
||||
for (var i=0; i < enabledDeviceList.length; i++) {
|
||||
id = enabledDeviceList[i];
|
||||
if (this.mapDeviceLayers.hasOwnProperty(id)) {
|
||||
this.toggleDevice(id, false, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toggleDevice: function(id, save=false, pageLoad=false) {
|
||||
var deviceLayer = this.deviceLayers[id];
|
||||
if (!deviceLayer.loaded) {
|
||||
this.loadDevicePoints(id, save, pageLoad);
|
||||
}
|
||||
this.toggleMapDeviceLayer(id);
|
||||
if (save) {
|
||||
this.saveEnabledDevices();
|
||||
this.updateMyFirstLastDates();
|
||||
}
|
||||
},
|
||||
|
||||
toggleMapDeviceLayer: function(id) {
|
||||
var mapDeviceLayer = this.mapDeviceLayers[id];
|
||||
var eyeButton = $('#device-list > li[device="'+id+'"] .toggleDeviceButton button');
|
||||
// hide device
|
||||
if (this.mainLayer.hasLayer(mapDeviceLayer)) {
|
||||
this.mainLayer.removeLayer(mapDeviceLayer);
|
||||
// color of the eye
|
||||
eyeButton.addClass('icon-toggle').attr('style', '');
|
||||
}
|
||||
// show track
|
||||
else {
|
||||
this.mainLayer.addLayer(mapDeviceLayer);
|
||||
// color of the eye
|
||||
var color = OCA.Theming.color.replace('#', '');
|
||||
var imgurl = OC.generateUrl('/svg/core/actions/toggle?color='+color);
|
||||
eyeButton.removeClass('icon-toggle').css('background-image', 'url('+imgurl+')');
|
||||
}
|
||||
},
|
||||
|
||||
loadDevicePoints: function(id, save=false, pageLoad=false) {
|
||||
var that = this;
|
||||
$('#device-list > li[device="'+id+'"]').addClass('icon-loading-small');
|
||||
var req = {};
|
||||
var url = OC.generateUrl('/apps/maps/devices/'+id);
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: url,
|
||||
data: req,
|
||||
async: true
|
||||
}).done(function (response) {
|
||||
that.addPoints(id, response);
|
||||
that.deviceLayers[id].loaded = true;
|
||||
that.updateMyFirstLastDates(pageLoad);
|
||||
}).always(function (response) {
|
||||
$('#device-list > li[device="'+id+'"]').removeClass('icon-loading-small');
|
||||
}).fail(function() {
|
||||
OC.Notification.showTemporary(t('maps', 'Failed to load device points'));
|
||||
});
|
||||
},
|
||||
|
||||
addPoints: function(id, points) {
|
||||
console.log('add points for device '+id);
|
||||
console.log(points);
|
||||
},
|
||||
|
||||
updateMyFirstLastDates: function(pageLoad=false) {
|
||||
if (!this.map.hasLayer(this.mainLayer)) {
|
||||
this.firstDate = null;
|
||||
this.lastDate = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var id;
|
||||
|
||||
// we update dates only if nothing is currently loading
|
||||
for (id in this.mapDeviceLayers) {
|
||||
if (this.mainLayer.hasLayer(this.mapDeviceLayers[id]) && !this.deviceLayers[id].loaded) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var initMinDate = Math.floor(Date.now() / 1000) + 1000000
|
||||
var initMaxDate = 0;
|
||||
|
||||
var first = initMinDate;
|
||||
var last = initMaxDate;
|
||||
for (id in this.mapDeviceLayers) {
|
||||
if (this.mainLayer.hasLayer(this.mapDeviceLayers[id]) && this.deviceLayers[id].loaded && this.devices[id].firstDate) {
|
||||
if (this.devices[id].firstDate < first) {
|
||||
first = this.devices[id].firstDate;
|
||||
}
|
||||
if (this.devices[id].lastDate > last) {
|
||||
last = this.device[id].lastDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (first !== initMinDate
|
||||
&& last !== initMaxDate) {
|
||||
this.firstDate = first;
|
||||
this.lastDate = last;
|
||||
}
|
||||
else {
|
||||
this.firstDate = null;
|
||||
this.lastDate = null;
|
||||
}
|
||||
if (pageLoad) {
|
||||
this.timeFilterController.updateSliderRangeFromController();
|
||||
this.timeFilterController.setSliderToMaxInterval();
|
||||
}
|
||||
},
|
||||
|
||||
sendMyPosition: function(lat, lng, acc) {
|
||||
var that = this;
|
||||
var ts = Math.floor(Date.now() / 1000);
|
||||
|
|
18
js/script.js
18
js/script.js
|
@ -99,6 +99,7 @@
|
|||
optionValues: {},
|
||||
enabledFavoriteCategories: [],
|
||||
enabledTracks: [],
|
||||
enabledDevices: [],
|
||||
saveOptionValues: function (optionValues) {
|
||||
var req = {
|
||||
options: optionValues
|
||||
|
@ -180,6 +181,23 @@
|
|||
if (!optionsValues.hasOwnProperty('tracksEnabled') || optionsValues.tracksEnabled === 'true') {
|
||||
tracksController.toggleTracks();
|
||||
}
|
||||
if (!optionsValues.hasOwnProperty('deviceListShow') || optionsValues.deviceListShow === 'true') {
|
||||
devicesController.toggleDeviceList();
|
||||
}
|
||||
if (optionsValues.hasOwnProperty('enabledDevices')
|
||||
&& optionsValues.enabledDevices
|
||||
&& optionsValues.enabledDevices !== '')
|
||||
{
|
||||
that.enabledDevices = optionsValues.enabledDevices.split('|').map(function (x) {
|
||||
return parseInt(x);
|
||||
});
|
||||
if (devicesController.deviceListLoaded) {
|
||||
devicesController.restoreDevicesState(that.enabledDevices);
|
||||
}
|
||||
}
|
||||
if (!optionsValues.hasOwnProperty('devicesEnabled') || optionsValues.devicesEnabled === 'true') {
|
||||
devicesController.toggleDevices();
|
||||
}
|
||||
|
||||
// save tile layer when changed
|
||||
// do it after restore, otherwise restoring triggers save
|
||||
|
|
|
@ -142,7 +142,7 @@ TracksController.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
// expand or fold categories in sidebar
|
||||
// expand or fold track list in sidebar
|
||||
toggleTrackList: function() {
|
||||
$('#navigation-tracks').toggleClass('open');
|
||||
},
|
||||
|
@ -465,6 +465,7 @@ TracksController.prototype = {
|
|||
|
||||
var beforeThis = null;
|
||||
var nameLower = name.toLowerCase();
|
||||
var trackName;
|
||||
$('#track-list > li').each(function() {
|
||||
trackName = $(this).attr('name');
|
||||
if (nameLower.localeCompare(trackName) < 0) {
|
||||
|
|
|
@ -82,10 +82,10 @@ class DevicesApiController extends ApiController {
|
|||
* @NoCSRFRequired
|
||||
* @CORS
|
||||
*/
|
||||
public function getDevices($apiversion, $pruneBefore=0) {
|
||||
public function getDevices($apiversion) {
|
||||
$now = new \DateTime();
|
||||
|
||||
$devices = $this->devicesService->getDevicesFromDB($this->userId, $pruneBefore);
|
||||
$devices = $this->devicesService->getDevicesFromDB($this->userId);
|
||||
|
||||
$etag = md5(json_encode($devices));
|
||||
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
|
||||
|
@ -96,6 +96,16 @@ class DevicesApiController extends ApiController {
|
|||
->setETag($etag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @CORS
|
||||
*/
|
||||
public function getDevicePoints($id, $pruneBefore=0) {
|
||||
$points = $this->devicesService->getDevicePointsFromDB($this->userId, $id, $pruneBefore);
|
||||
return new DataResponse($points);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
|
@ -113,7 +123,10 @@ class DevicesApiController extends ApiController {
|
|||
}
|
||||
$deviceId = $this->devicesService->getOrCreateDeviceFromDB($this->userId, $ua);
|
||||
$pointId = $this->devicesService->addPointToDB($deviceId, $lat, $lng, $ts, $altitude, $battery, $accuracy);
|
||||
return new DataResponse($pointId);
|
||||
return new DataResponse([
|
||||
'deviceId'=>$deviceId,
|
||||
'pointId'=>$pointId
|
||||
]);
|
||||
}
|
||||
else {
|
||||
return new DataResponse('invalid values', 400);
|
||||
|
|
|
@ -82,11 +82,19 @@ class DevicesController extends Controller {
|
|||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function getDevices($pruneBefore=0) {
|
||||
$devices = $this->devicesService->getDevicesFromDB($this->userId, $pruneBefore);
|
||||
public function getDevices() {
|
||||
$devices = $this->devicesService->getDevicesFromDB($this->userId);
|
||||
return new DataResponse($devices);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function getDevicePoints($id, $pruneBefore=0) {
|
||||
$points = $this->devicesService->getDevicePointsFromDB($this->userId, $id, $pruneBefore);
|
||||
return new DataResponse($points);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
|
@ -102,7 +110,10 @@ class DevicesController extends Controller {
|
|||
}
|
||||
$deviceId = $this->devicesService->getOrCreateDeviceFromDB($this->userId, $ua);
|
||||
$pointId = $this->devicesService->addPointToDB($deviceId, $lat, $lng, $ts, $altitude, $battery, $accuracy);
|
||||
return new DataResponse($pointId);
|
||||
return new DataResponse([
|
||||
'deviceId'=>$deviceId,
|
||||
'pointId'=>$pointId
|
||||
]);
|
||||
}
|
||||
else {
|
||||
return new DataResponse('invalid values', 400);
|
||||
|
|
|
@ -33,56 +33,7 @@ class DevicesService {
|
|||
* @param int $pruneBefore
|
||||
* @return array with devices
|
||||
*/
|
||||
public function getDevicesFromDB($userId, $pruneBefore=0) {
|
||||
$deviceIds = [];
|
||||
$qb = $this->qb;
|
||||
$qb->select('id')
|
||||
->from('maps_devices', 'd')
|
||||
->where(
|
||||
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
|
||||
);
|
||||
$req = $qb->execute();
|
||||
|
||||
while ($row = $req->fetch()) {
|
||||
array_push($deviceIds, intval($row['id']));
|
||||
}
|
||||
$req->closeCursor();
|
||||
$qb = $qb->resetQueryParts();
|
||||
|
||||
// get coordinates
|
||||
$pointsByDevice = [];
|
||||
foreach ($deviceIds as $deviceId) {
|
||||
$qb->select('id', 'lat', 'lng', 'timestamp', 'altitude', 'accuracy', 'battery')
|
||||
->from('maps_device_points', 'p')
|
||||
->where(
|
||||
$qb->expr()->eq('device_id', $qb->createNamedParameter($deviceId, IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
if (intval($pruneBefore) > 0) {
|
||||
$qb->andWhere(
|
||||
$qb->expr()->gt('timestamp', $qb->createNamedParameter($pruneBefore, IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
}
|
||||
$qb->orderBy('timestamp', 'ASC');
|
||||
$req = $qb->execute();
|
||||
|
||||
$points = [];
|
||||
while ($row = $req->fetch()) {
|
||||
array_push($points, [
|
||||
'id' => intval($row['id']),
|
||||
'lat' => floatval($row['lat']),
|
||||
'lng' => floatval($row['lng']),
|
||||
'timestamp' => intval($row['timestamp']),
|
||||
'altitude' => floatval($row['altitude']),
|
||||
'accuracy' => floatval($row['accuracy']),
|
||||
'battery' => floatval($row['battery'])
|
||||
]);
|
||||
}
|
||||
$pointsByDevice[$deviceId] = $points;
|
||||
}
|
||||
$req->closeCursor();
|
||||
$qb = $qb->resetQueryParts();
|
||||
|
||||
// build device list
|
||||
public function getDevicesFromDB($userId) {
|
||||
$devices = [];
|
||||
$qb = $this->qb;
|
||||
$qb->select('id', 'user_agent', 'color')
|
||||
|
@ -96,8 +47,7 @@ class DevicesService {
|
|||
array_push($devices, [
|
||||
'id' => intval($row['id']),
|
||||
'user_agent' => $row['user_agent'],
|
||||
'color' => $row['color'],
|
||||
'points' => $pointsByDevice[intval($row['id'])]
|
||||
'color' => $row['color']
|
||||
]);
|
||||
}
|
||||
$req->closeCursor();
|
||||
|
@ -105,6 +55,45 @@ class DevicesService {
|
|||
return $devices;
|
||||
}
|
||||
|
||||
public function getDevicePointsFromDB($userId, $deviceId, $pruneBefore=0) {
|
||||
$qb = $this->qb;
|
||||
// get coordinates
|
||||
$qb->select('p.id', 'lat', 'lng', 'timestamp', 'altitude', 'accuracy', 'battery')
|
||||
->from('maps_device_points', 'p')
|
||||
->innerJoin('p', 'maps_devices', 'd', $qb->expr()->eq('d.id', 'p.device_id'))
|
||||
->where(
|
||||
$qb->expr()->eq('p.device_id', $qb->createNamedParameter($deviceId, IQueryBuilder::PARAM_INT))
|
||||
)
|
||||
->andWhere(
|
||||
$qb->expr()->eq('d.user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
|
||||
);
|
||||
if (intval($pruneBefore) > 0) {
|
||||
$qb->andWhere(
|
||||
$qb->expr()->gt('timestamp', $qb->createNamedParameter($pruneBefore, IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
}
|
||||
$qb->orderBy('timestamp', 'ASC');
|
||||
error_log($qb->getSQL());
|
||||
$req = $qb->execute();
|
||||
|
||||
$points = [];
|
||||
while ($row = $req->fetch()) {
|
||||
array_push($points, [
|
||||
'id' => intval($row['id']),
|
||||
'lat' => floatval($row['lat']),
|
||||
'lng' => floatval($row['lng']),
|
||||
'timestamp' => intval($row['timestamp']),
|
||||
'altitude' => floatval($row['altitude']),
|
||||
'accuracy' => floatval($row['accuracy']),
|
||||
'battery' => floatval($row['battery'])
|
||||
]);
|
||||
}
|
||||
$req->closeCursor();
|
||||
$qb = $qb->resetQueryParts();
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
public function getOrCreateDeviceFromDB($userId, $userAgent) {
|
||||
$deviceId = null;
|
||||
$qb = $this->qb;
|
||||
|
@ -216,7 +205,7 @@ class DevicesService {
|
|||
$qb = $this->dbconnection->getQueryBuilder();
|
||||
$qb->select($qb->createFunction('COUNT(*)'))
|
||||
->from('maps_devices', 'd')
|
||||
->innerJoin('bo', 'maps_device_points', 'p', $qb->expr()->eq('d.id', 'p.device_id'))
|
||||
->innerJoin('d', 'maps_device_points', 'p', $qb->expr()->eq('d.id', 'p.device_id'))
|
||||
->where(
|
||||
$qb->expr()->eq('d.user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
|
|
Загрузка…
Ссылка в новой задаче