Compare commits
3 Commits
de8a3f07e5
...
17828fe9ce
| Author | SHA1 | Date | |
|---|---|---|---|
| 17828fe9ce | |||
| 7585d475a7 | |||
| 1bcdef230c |
@@ -9,7 +9,9 @@
|
|||||||
|
|
||||||
//Ctrl+Alt+Shift+I to open network tab on addon
|
//Ctrl+Alt+Shift+I to open network tab on addon
|
||||||
|
|
||||||
var gpxParser = function () {
|
/* GPXParser - v3.0.6 - https://github.com/Luuka/GPXParser.js/blob/master/src/GPXParser.js */
|
||||||
|
/* Personnal modifications have been applied, care on upgrade */
|
||||||
|
let gpxParser = function () {
|
||||||
this.xmlSource = "";
|
this.xmlSource = "";
|
||||||
this.metadata = {};
|
this.metadata = {};
|
||||||
this.waypoints = [];
|
this.waypoints = [];
|
||||||
@@ -18,8 +20,9 @@ var gpxParser = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
gpxParser.prototype.parse = function (gpxstring) {
|
gpxParser.prototype.parse = function (gpxstring) {
|
||||||
var keepThis = this;
|
let keepThis = this;
|
||||||
var domParser = new window.DOMParser();
|
|
||||||
|
let domParser = new window.DOMParser();
|
||||||
this.xmlSource = domParser.parseFromString(gpxstring, 'text/xml');
|
this.xmlSource = domParser.parseFromString(gpxstring, 'text/xml');
|
||||||
|
|
||||||
metadata = this.xmlSource.querySelector('metadata');
|
metadata = this.xmlSource.querySelector('metadata');
|
||||||
@@ -70,13 +73,18 @@ gpxParser.prototype.parse = function (gpxstring) {
|
|||||||
pt.ele = parseFloat(keepThis.getElementValue(wpt, "ele")) || null;
|
pt.ele = parseFloat(keepThis.getElementValue(wpt, "ele")) || null;
|
||||||
pt.cmt = keepThis.getElementValue(wpt, "cmt");
|
pt.cmt = keepThis.getElementValue(wpt, "cmt");
|
||||||
pt.desc = keepThis.getElementValue(wpt, "desc");
|
pt.desc = keepThis.getElementValue(wpt, "desc");
|
||||||
pt.sym = keepThis.getElementValue(wpt, "sym");
|
pt.sym = keepThis.getElementValue(wpt, "sym");
|
||||||
|
|
||||||
|
//let time = keepThis.getElementValue(wpt, "time");
|
||||||
|
//pt.time = time == null ? null : new Date(time);
|
||||||
|
pt.time = (keepThis.getElementValue(wpt, "time") || keepThis.metadata.time) || null;;
|
||||||
|
|
||||||
keepThis.waypoints.push(pt);
|
keepThis.waypoints.push(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rtes = [].slice.call(this.xmlSource.querySelectorAll('rte'));
|
var rtes = [].slice.call(this.xmlSource.querySelectorAll('rte'));
|
||||||
for (let idx in rtes){
|
for (let idx in rtes){
|
||||||
var rte = rtes[idx];
|
let rte = rtes[idx];
|
||||||
let route = {};
|
let route = {};
|
||||||
route.name = keepThis.getElementValue(rte, "name");
|
route.name = keepThis.getElementValue(rte, "name");
|
||||||
route.cmt = keepThis.getElementValue(rte, "cmt");
|
route.cmt = keepThis.getElementValue(rte, "cmt");
|
||||||
@@ -100,21 +108,30 @@ gpxParser.prototype.parse = function (gpxstring) {
|
|||||||
var rtepts = [].slice.call(rte.querySelectorAll('rtept'));
|
var rtepts = [].slice.call(rte.querySelectorAll('rtept'));
|
||||||
|
|
||||||
for (let idxIn in rtepts){
|
for (let idxIn in rtepts){
|
||||||
var rtept = rtepts[idxIn];
|
let rtept = rtepts[idxIn];
|
||||||
let pt = {};
|
let pt = {};
|
||||||
pt.lat = parseFloat(rtept.getAttribute("lat"));
|
pt.lat = parseFloat(rtept.getAttribute("lat"));
|
||||||
pt.lon = parseFloat(rtept.getAttribute("lon"));
|
pt.lon = parseFloat(rtept.getAttribute("lon"));
|
||||||
pt.ele = parseFloat(keepThis.getElementValue(rtept, "ele"));
|
pt.ele = parseFloat(keepThis.getElementValue(rtept, "ele")) || null;
|
||||||
|
|
||||||
|
//let time = keepThis.getElementValue(rtept, "time");
|
||||||
|
//pt.time = time == null ? null : new Date(time);
|
||||||
|
pt.time = (keepThis.getElementValue(rtept, "time") || keepThis.metadata.time) || null;
|
||||||
|
|
||||||
routepoints.push(pt);
|
routepoints.push(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//route.distance = keepThis.calculDistance(routepoints);
|
||||||
|
//route.elevation = keepThis.calcElevation(routepoints);
|
||||||
|
//route.slopes = keepThis.calculSlope(routepoints, route.distance.cumul);
|
||||||
route.points = routepoints;
|
route.points = routepoints;
|
||||||
|
|
||||||
keepThis.routes.push(route);
|
keepThis.routes.push(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
var trks = [].slice.call(this.xmlSource.querySelectorAll('trk'));
|
var trks = [].slice.call(this.xmlSource.querySelectorAll('trk'));
|
||||||
for (let idx in trks){
|
for (let idx in trks){
|
||||||
var trk = trks[idx];
|
let trk = trks[idx];
|
||||||
let track = {};
|
let track = {};
|
||||||
|
|
||||||
track.name = keepThis.getElementValue(trk, "name");
|
track.name = keepThis.getElementValue(trk, "name");
|
||||||
@@ -123,8 +140,10 @@ gpxParser.prototype.parse = function (gpxstring) {
|
|||||||
track.src = keepThis.getElementValue(trk, "src");
|
track.src = keepThis.getElementValue(trk, "src");
|
||||||
track.number = keepThis.getElementValue(trk, "number");
|
track.number = keepThis.getElementValue(trk, "number");
|
||||||
track.color = keepThis.getElementValue(trk, "DisplayColor");
|
track.color = keepThis.getElementValue(trk, "DisplayColor");
|
||||||
|
track.time = keepThis.metadata.time;
|
||||||
|
|
||||||
let type = keepThis.queryDirectSelector(trk, "type");
|
let type = keepThis.queryDirectSelector(trk, "type");
|
||||||
|
track.type = type != null ? type.innerHTML : null;
|
||||||
|
|
||||||
let link = {};
|
let link = {};
|
||||||
let linkElem = trk.querySelector('link');
|
let linkElem = trk.querySelector('link');
|
||||||
@@ -136,15 +155,23 @@ gpxParser.prototype.parse = function (gpxstring) {
|
|||||||
track.link = link;
|
track.link = link;
|
||||||
|
|
||||||
let trackpoints = [];
|
let trackpoints = [];
|
||||||
var trkpts = [].slice.call(trk.querySelectorAll('trkpt'));
|
let trkpts = [].slice.call(trk.querySelectorAll('trkpt'));
|
||||||
for (let idxIn in trkpts){
|
for (let idxIn in trkpts){
|
||||||
var trkpt = trkpts[idxIn];
|
var trkpt = trkpts[idxIn];
|
||||||
let pt = {};
|
let pt = {};
|
||||||
pt.lat = parseFloat(trkpt.getAttribute("lat"));
|
pt.lat = parseFloat(trkpt.getAttribute("lat"));
|
||||||
pt.lon = parseFloat(trkpt.getAttribute("lon"));
|
pt.lon = parseFloat(trkpt.getAttribute("lon"));
|
||||||
pt.ele = parseFloat(keepThis.getElementValue(trkpt, "ele")) || null;
|
pt.ele = parseFloat(keepThis.getElementValue(trkpt, "ele")) || null;
|
||||||
|
|
||||||
|
//let time = keepThis.getElementValue(trkpt, "time");
|
||||||
|
//pt.time = time == null ? null : new Date(time);
|
||||||
|
pt.time = (keepThis.getElementValue(trkpt, "time") || keepThis.metadata.time) || null;
|
||||||
|
|
||||||
trackpoints.push(pt);
|
trackpoints.push(pt);
|
||||||
}
|
}
|
||||||
|
//track.distance = keepThis.calculDistance(trackpoints);
|
||||||
|
//track.elevation = keepThis.calcElevation(trackpoints);
|
||||||
|
//track.slopes = keepThis.calculSlope(trackpoints, track.distance.cumul);
|
||||||
track.points = trackpoints;
|
track.points = trackpoints;
|
||||||
|
|
||||||
keepThis.tracks.push(track);
|
keepThis.tracks.push(track);
|
||||||
@@ -179,6 +206,88 @@ gpxParser.prototype.queryDirectSelector = function(parent, needle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
gpxParser.prototype.calculDistance = function(points) {
|
||||||
|
let distance = {};
|
||||||
|
let totalDistance = 0;
|
||||||
|
let cumulDistance = [];
|
||||||
|
for (var i = 0; i < points.length - 1; i++) {
|
||||||
|
totalDistance += this.calcDistanceBetween(points[i],points[i+1]);
|
||||||
|
cumulDistance[i] = totalDistance;
|
||||||
|
}
|
||||||
|
cumulDistance[points.length - 1] = totalDistance;
|
||||||
|
|
||||||
|
distance.total = totalDistance;
|
||||||
|
distance.cumul = cumulDistance;
|
||||||
|
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpxParser.prototype.calcDistanceBetween = function (wpt1, wpt2) {
|
||||||
|
let latlng1 = {};
|
||||||
|
latlng1.lat = wpt1.lat;
|
||||||
|
latlng1.lon = wpt1.lon;
|
||||||
|
let latlng2 = {};
|
||||||
|
latlng2.lat = wpt2.lat;
|
||||||
|
latlng2.lon = wpt2.lon;
|
||||||
|
var rad = Math.PI / 180,
|
||||||
|
lat1 = latlng1.lat * rad,
|
||||||
|
lat2 = latlng2.lat * rad,
|
||||||
|
sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
|
||||||
|
sinDLon = Math.sin((latlng2.lon - latlng1.lon) * rad / 2),
|
||||||
|
a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
|
||||||
|
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
return 6371000 * c;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpxParser.prototype.calcElevation = function (points) {
|
||||||
|
var dp = 0,
|
||||||
|
dm = 0,
|
||||||
|
ret = {};
|
||||||
|
|
||||||
|
for (var i = 0; i < points.length - 1; i++) {
|
||||||
|
var diff = parseFloat(points[i + 1].ele) - parseFloat(points[i].ele);
|
||||||
|
|
||||||
|
if (diff < 0) {
|
||||||
|
dm += diff;
|
||||||
|
} else if (diff > 0) {
|
||||||
|
dp += diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var elevation = [];
|
||||||
|
var sum = 0;
|
||||||
|
|
||||||
|
for (var i = 0, len = points.length; i < len; i++) {
|
||||||
|
var ele = parseFloat(points[i].ele);
|
||||||
|
elevation.push(ele);
|
||||||
|
sum += ele;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.max = Math.max.apply(null, elevation) || null;
|
||||||
|
ret.min = Math.min.apply(null, elevation) || null;
|
||||||
|
ret.pos = Math.abs(dp) || null;
|
||||||
|
ret.neg = Math.abs(dm) || null;
|
||||||
|
ret.avg = sum / elevation.length || null;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
gpxParser.prototype.calculSlope = function(points, cumul) {
|
||||||
|
let slopes = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < points.length - 1; i++) {
|
||||||
|
let point = points[i];
|
||||||
|
let nextPoint = points[i+1];
|
||||||
|
let elevationDiff = nextPoint.ele - point.ele;
|
||||||
|
let distance = cumul[i+1] - cumul[i];
|
||||||
|
|
||||||
|
let slope = (elevationDiff * 100) / distance;
|
||||||
|
slopes.push(slope);
|
||||||
|
}
|
||||||
|
|
||||||
|
return slopes;
|
||||||
|
}
|
||||||
|
|
||||||
gpxParser.prototype.toGeoJSON = function () {
|
gpxParser.prototype.toGeoJSON = function () {
|
||||||
var GeoJSON = {
|
var GeoJSON = {
|
||||||
"type": "FeatureCollection",
|
"type": "FeatureCollection",
|
||||||
@@ -287,7 +396,11 @@ gpxParser.prototype.toGeoJSON = function () {
|
|||||||
|
|
||||||
return GeoJSON;
|
return GeoJSON;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
if(typeof module !== 'undefined'){
|
||||||
|
require('jsdom-global')();
|
||||||
|
module.exports = gpxParser;
|
||||||
|
}
|
||||||
|
|
||||||
gpxParser.prototype.getGPX = function(sName) {
|
gpxParser.prototype.getGPX = function(sName) {
|
||||||
var sTrack = '';
|
var sTrack = '';
|
||||||
@@ -315,31 +428,63 @@ gpxParser.prototype.getGPX = function(sName) {
|
|||||||
|
|
||||||
return sGPX;
|
return sGPX;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
class Gaia {
|
class Gaia {
|
||||||
static get URL() { return 'https://www.gaiagps.com'; }
|
static get URL() { return 'https://www.gaiagps.com'; }
|
||||||
static get API() { return Gaia.URL+'/api/objects'; }
|
static get API() { return Gaia.URL+'/api/objects'; }
|
||||||
|
|
||||||
constructor($InputFile, $InputButton) {
|
constructor() {
|
||||||
this.asFiles = [];
|
this.asFiles = [];
|
||||||
this.aoWaypoints = [];
|
this.aoWaypoints = [];
|
||||||
this.aoTracks = [];
|
this.aoTracks = [];
|
||||||
this.sFolderId = '';
|
this.sFolderId = '';
|
||||||
this.asFolder = {};
|
this.asFolder = {};
|
||||||
this.sFolderName = '';
|
this.sFolderName = '';
|
||||||
this.$Feedback = $('<div>', {'style':'position:fixed;width:100%;height:25%;bottom:0;background:white;z-index:10000;border-top:1px solid #CCC;box-sizing:border-box;font-size:1.2em;overflow:auto;padding:0 1em;'});
|
this.progress = {current:0, total:0};
|
||||||
this.$InputName = $('<input>', {'type':'text', 'name':'folder_name', 'placeholder':'Folder Name', 'style': 'border-width:2px; border-color:rgba(0, 0, 0, 0.1); border-radius:4px; font-family:Inter,Helvetica Neue,Helvetica,Arial; font-size:15px; padding:8px 12px; margin-bottom:12px;'});
|
}
|
||||||
|
|
||||||
this.$InputBox = $InputButton.parent();
|
/* FIXME: adapts on GaiaGPS upgrade */
|
||||||
|
setLayout() {
|
||||||
|
let $InputButton = $('a[href="https://help.gaiagps.com/hc/en-us/articles/360052763513"]').parent().find('button');
|
||||||
|
|
||||||
//Reboot object to remove events
|
//If the button is found (=displayed)
|
||||||
this.$InputFile = $InputFile.clone().insertAfter($InputFile);
|
if($InputButton.length > 0) {
|
||||||
$InputFile.remove();
|
this.$InputBox = $InputButton.parent();
|
||||||
|
|
||||||
this.$InputButton = $InputButton.clone().insertAfter($InputButton);
|
//Add Feedback box
|
||||||
$InputButton.remove();
|
this.$Feedback = ($('#ggu-feedback').length > 0)?$('#ggu-feedback'):($('<div>', {
|
||||||
|
'id':'ggu-feedback',
|
||||||
|
'style':'width:calc(100% + 64px); height:400px; margin:1em 0 0 -32px; display:inline-block; text-align:left; overflow:auto;'
|
||||||
|
}).insertAfter($InputButton));
|
||||||
|
|
||||||
this.setLayout();
|
//Add Folder Name Input next to button
|
||||||
|
this.$InputName = ($('#ggu-inputname').length > 0)?$('#ggu-inputname'):($('<input>', {
|
||||||
|
'type':'text',
|
||||||
|
'id': 'ggu-inputname',
|
||||||
|
'name':'ggu-inputname',
|
||||||
|
'placeholder':'Folder Name',
|
||||||
|
'style': 'border-width:2px; border-color:rgba(0, 0, 0, 0.1); border-radius:4px; font-family:Inter,Helvetica Neue,Helvetica,Arial; font-size:15px; padding:8px 12px; margin-bottom:12px;'
|
||||||
|
}).val('PCT').prependTo(this.$InputBox));
|
||||||
|
|
||||||
|
//Reset File Input
|
||||||
|
let $InputFile = $('input[type=file]');
|
||||||
|
this.$InputFile = $InputFile.clone()
|
||||||
|
.insertAfter($InputFile)
|
||||||
|
.attr('multiple', 'multiple')
|
||||||
|
.attr('name', 'files[]')
|
||||||
|
.change(() => { this.readInputFiles(); });
|
||||||
|
$InputFile.remove();
|
||||||
|
|
||||||
|
//Reset button
|
||||||
|
this.$InputButton = $InputButton.clone()
|
||||||
|
.insertAfter($InputButton)
|
||||||
|
.click(() => {this.$InputFile.click();});
|
||||||
|
$InputButton.remove();
|
||||||
|
|
||||||
|
//Clear all upload notifications
|
||||||
|
this.resetNotif();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
feedback(sType, sMsg) {
|
feedback(sType, sMsg) {
|
||||||
@@ -350,32 +495,45 @@ class Gaia {
|
|||||||
switch(sType) {
|
switch(sType) {
|
||||||
case 'error': sColor = 'red'; break;
|
case 'error': sColor = 'red'; break;
|
||||||
case 'warning': sColor = 'orange'; break;
|
case 'warning': sColor = 'orange'; break;
|
||||||
case 'info': sColor = 'green'; break;
|
case 'info': sColor = '#2D5E38'; break;
|
||||||
}
|
}
|
||||||
this.$Feedback.append($('<p>', {'style': 'color: '+sColor+';'}).text(sFormattedMsg));
|
this.$Feedback.append($('<p>', {'style': 'color: '+sColor+';'}).text(sFormattedMsg));
|
||||||
|
|
||||||
this.$Feedback.scrollTop(this.$Feedback.prop("scrollHeight"));
|
this.$Feedback.scrollTop(this.$Feedback.prop("scrollHeight"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Modify Gaia DOM Interface
|
incProgress() {
|
||||||
setLayout() {
|
if(!this.progress.current) {
|
||||||
//Add Feedback box
|
this.progress.$Done = $('<div>', {'style':'overflow:hidden; background:#2D5E38; color: white; text-align:right;'});
|
||||||
this.$Feedback.appendTo($('body'));
|
this.progress.$Left = $('<div>', {'style':'overflow:hidden; background:white; color: #2D5E38; text-align:left;'});
|
||||||
|
this.progress.$Box = $('<div>', {'id':'ggu-progress', 'style':'margin-top:1em;'})
|
||||||
|
.append($('<div>', {'style':'display:flex; width:calc(100% + 64px); margin-left:-32px; border-radius:3px; border: 1px solid #2D5E38; box-sizing: border-box;'})
|
||||||
|
.append(this.progress.$Done)
|
||||||
|
.append(this.progress.$Left)
|
||||||
|
);
|
||||||
|
this.$Feedback.before(this.progress.$Box);
|
||||||
|
}
|
||||||
|
|
||||||
//Add Event on button
|
this.progress.current++;
|
||||||
this.$InputButton.click(() => {this.$InputFile.click();});
|
|
||||||
|
|
||||||
//Set event on file selection
|
if(this.progress.current < this.progress.total) {
|
||||||
this.$InputFile
|
let iRatio = Math.round(this.progress.current / this.progress.total * 100);
|
||||||
.attr('multiple', 'multiple')
|
let sTextDone = '', sTextLeft = '';
|
||||||
.attr('name', 'files[]')
|
if(iRatio < 50) {
|
||||||
.change(() => {this.readInputFiles();});
|
sTextDone = '';
|
||||||
|
sTextLeft = ' '+iRatio+'% ('+this.progress.current+' / '+this.progress.total+')';
|
||||||
//Set default Name
|
}
|
||||||
this.$InputName.val('PCT').prependTo(this.$InputBox);
|
else {
|
||||||
|
sTextDone = '('+this.progress.current+' / '+this.progress.total+') '+iRatio+'% ';
|
||||||
//Clear all upload notifications
|
sTextLeft = '';
|
||||||
this.resetNotif();
|
}
|
||||||
|
this.progress.$Done.css('flex', iRatio+' 1 0%').html(sTextDone);
|
||||||
|
this.progress.$Left.css('flex', (100 - iRatio)+' 1 0%').html(sTextLeft);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.progress.$Box.remove();
|
||||||
|
this.progress = {current:0, total:0};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Marking all upload notifications as read
|
//Marking all upload notifications as read
|
||||||
@@ -410,7 +568,10 @@ class Gaia {
|
|||||||
iCount++;
|
iCount++;
|
||||||
this.feedback('info', 'Reading file "'+oFileReader.name+'" ('+iCount+'/'+this.asFiles.length+')');
|
this.feedback('info', 'Reading file "'+oFileReader.name+'" ('+iCount+'/'+this.asFiles.length+')');
|
||||||
this.parseFile(oFileReader.name, asResult.target.result);
|
this.parseFile(oFileReader.name, asResult.target.result);
|
||||||
if(iCount == this.asFiles.length) this.createFolder();
|
if(iCount == this.asFiles.length) {
|
||||||
|
this.progress.total = this.aoTracks.length + this.aoWaypoints.length + 2; //+1: Create forlder +1: Assign objects to folder
|
||||||
|
this.createFolder();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})(this.asFiles[i]);
|
})(this.asFiles[i]);
|
||||||
aoReaders[i].readAsText(this.asFiles[i]);
|
aoReaders[i].readAsText(this.asFiles[i]);
|
||||||
@@ -467,115 +628,103 @@ class Gaia {
|
|||||||
this.asFolder = asFolder;
|
this.asFolder = asFolder;
|
||||||
this.sFolderId = asFolder.id;
|
this.sFolderId = asFolder.id;
|
||||||
this.sFolderName = asFolder.properties.name;
|
this.sFolderName = asFolder.properties.name;
|
||||||
|
this.incProgress();
|
||||||
this.uploadTrack();
|
this.uploadTrack();
|
||||||
|
}).fail(() => {
|
||||||
|
this.feedback('error', 'Folder "'+this.sFolderName+'" could not be created');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build & Upload Track File
|
//Build & Upload Track File
|
||||||
uploadTrack() {
|
uploadTrack(iIndex) {
|
||||||
this.feedback('info', 'Uploading tracks...');
|
iIndex = iIndex || 0;
|
||||||
|
|
||||||
|
if(iIndex == 0) this.feedback('info', 'Uploading tracks...');
|
||||||
|
|
||||||
|
let aoTrack = this.aoTracks[iIndex];
|
||||||
|
this.feedback('info', 'Uploading track "'+aoTrack.name+'"');
|
||||||
|
|
||||||
|
//Set color
|
||||||
|
let sColor = '#4ABD32';
|
||||||
|
switch(aoTrack.color) {
|
||||||
|
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
||||||
|
case 'Magenta': sColor = '#B60DC3'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add track points
|
||||||
|
let aoCoords = [];
|
||||||
|
for(var p in aoTrack.points) {
|
||||||
|
let pt = aoTrack.points[p];
|
||||||
|
aoCoords.push([pt.lon, pt.lat, pt.ele, 0]);
|
||||||
|
}
|
||||||
|
|
||||||
//Convert to geojson
|
//Convert to geojson
|
||||||
let iPostedTracks = 0;
|
let sPostedData = JSON.stringify({
|
||||||
$.each(this.aoTracks, (iIndex, aoTrack) => {
|
type: 'feature',
|
||||||
|
properties: {
|
||||||
//Set color
|
color: sColor,
|
||||||
let sColor = '#4ABD32';
|
title: aoTrack.name,
|
||||||
switch(aoTrack.color) {
|
time_created: aoTrack.time,
|
||||||
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
routing_mode: null,
|
||||||
case 'Magenta': sColor = '#B60DC3'; break;
|
notes: aoTrack.desc,
|
||||||
|
//distance: 168405.62350073704,
|
||||||
|
isValid: true,
|
||||||
|
isLatestImport: true,
|
||||||
|
filename: aoTrack.filename,
|
||||||
|
localId: 'track'+(iIndex + 1),
|
||||||
|
writable: true,
|
||||||
|
archived: false,
|
||||||
|
isPublicTrack: false,
|
||||||
|
isLocallyCreated: true,
|
||||||
|
type: 'track',
|
||||||
|
parent_folder_id: this.sFolderId,
|
||||||
|
hexcolor: sColor
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'MultiLineString',
|
||||||
|
coordinates: [aoCoords]
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add track points
|
|
||||||
let aoCoords = [];
|
|
||||||
for(var p in aoTrack.points) {
|
|
||||||
let pt = aoTrack.points[p];
|
|
||||||
aoCoords.push([pt.lon, pt.lat, pt.ele, 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Upload
|
|
||||||
let sPostedData = JSON.stringify({
|
|
||||||
type: 'feature',
|
|
||||||
properties: {
|
|
||||||
color: sColor,
|
|
||||||
title: aoTrack.name,
|
|
||||||
time_created: '2020-12-27T11:34:03.537Z',
|
|
||||||
routing_mode: null,
|
|
||||||
notes: aoTrack.desc,
|
|
||||||
//distance: 168405.62350073704,
|
|
||||||
isValid: true,
|
|
||||||
isLatestImport: true,
|
|
||||||
filename: aoTrack.filename,
|
|
||||||
localId: 'track'+(iIndex + 1),
|
|
||||||
writable: true,
|
|
||||||
archived: false,
|
|
||||||
isPublicTrack: false,
|
|
||||||
isLocallyCreated: true,
|
|
||||||
type: 'track',
|
|
||||||
parent_folder_id: this.sFolderId,
|
|
||||||
hexcolor: sColor
|
|
||||||
},
|
|
||||||
geometry: {
|
|
||||||
type: 'MultiLineString',
|
|
||||||
coordinates: [aoCoords]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.feedback('info', 'Uploading track "'+aoTrack.name+'"');
|
|
||||||
$.post({
|
|
||||||
url: Gaia.API+'/track/',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: sPostedData,
|
|
||||||
postedData: sPostedData,
|
|
||||||
trackName: aoTrack.name
|
|
||||||
}).done(function(asTrack) {
|
|
||||||
self.aoTracks[iIndex] = asTrack;
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: Gaia.API+'/track/'+asTrack.features[0].id+'/',
|
|
||||||
type: 'PUT',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: this.postedData,
|
|
||||||
trackName: this.trackName
|
|
||||||
}).done(function() {
|
|
||||||
iPostedTracks++;
|
|
||||||
self.feedback('info', 'Track "'+this.trackName+'" uploaded');
|
|
||||||
if(iPostedTracks == self.aoTracks.length) {
|
|
||||||
self.feedback('info', 'All tracks uploaded');
|
|
||||||
self.uploadWayPoints();
|
|
||||||
}
|
|
||||||
}).fail(function() {
|
|
||||||
self.feedback('error', 'Track "'+this.trackName+'" failed to upload');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Legacy lethod: through form submit
|
var self = this;
|
||||||
|
$.post({
|
||||||
|
url: Gaia.API+'/track/',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: sPostedData,
|
||||||
|
trackName: aoTrack.name
|
||||||
|
}).done(function(asTrack) {
|
||||||
|
self.aoTracks[iIndex] = asTrack;
|
||||||
|
self.confirmTrack(iIndex, asTrack, this.data);
|
||||||
|
}).fail(function() {
|
||||||
|
self.feedback('error', 'Track "'+this.trackName+'" upload failed (stage 1). Retrying...');
|
||||||
|
self.uploadTrack(iIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//Build track file
|
confirmTrack(iIndex, asTrack, sPostedData) {
|
||||||
this.feedback('info', 'Building consolidated track');
|
iIndex = iIndex || 0;
|
||||||
var oGPX = new gpxParser();
|
|
||||||
oGPX.tracks = this.aoTracks;
|
|
||||||
var sTrack = oGPX.getGPX(this.sFolderName);
|
|
||||||
|
|
||||||
//Send consolidated Tracks as one file
|
var self = this;
|
||||||
var oForm = new FormData();
|
|
||||||
oForm.append('name', this.sFolderName);
|
|
||||||
oForm.append('files', new Blob([sTrack]), 'Consolidated.gpx');
|
|
||||||
|
|
||||||
this.feedback('info', 'Uploading consolidated track');
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: Gaia.URL+'/upload/',
|
url: Gaia.API+'/track/'+asTrack.features[0].id+'/',
|
||||||
type: 'POST',
|
type: 'PUT',
|
||||||
data: oForm,
|
contentType: 'application/json',
|
||||||
enctype: 'multipart/form-data',
|
data: sPostedData,
|
||||||
processData: false,
|
trackName: asTrack.features[0].properties.title
|
||||||
contentType: false,
|
}).done(function() {
|
||||||
cache: false
|
self.feedback('info', 'Track "'+this.trackName+'" uploaded');
|
||||||
}).done(() => {this.checkNotif();});
|
self.incProgress();
|
||||||
*/
|
iIndex++;
|
||||||
|
if(iIndex < self.aoTracks.length) self.uploadTrack(iIndex);
|
||||||
|
else {
|
||||||
|
self.feedback('info', 'All tracks uploaded');
|
||||||
|
self.uploadWayPoints();
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
self.feedback('error', 'Track "'+this.trackName+'" upload failed (stage 2). Retrying...');
|
||||||
|
self.confirmTrack(iIndex, asTrack, sPostedData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -599,115 +748,72 @@ class Gaia {
|
|||||||
else setTimeout((() => {this.checkNotif();}), 1000);
|
else setTimeout((() => {this.checkNotif();}), 1000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Convert QMapshack Track Colors into Gaia Colors
|
|
||||||
setTracksColor() {
|
|
||||||
this.feedback('info', 'Track Color - Matching Gaia track IDs with GPX tracks');
|
|
||||||
var iCount = 0;
|
|
||||||
|
|
||||||
$.get(Gaia.API+'/folder/'+this.sFolderId+'/').done((asFolder) => {
|
|
||||||
var self = this;
|
|
||||||
for(var iGaiaIndex in asFolder.properties.tracks) {
|
|
||||||
for(var iGpxIndex in this.aoTracks) {
|
|
||||||
if(asFolder.properties.tracks[iGaiaIndex].title == this.aoTracks[iGpxIndex].name) {
|
|
||||||
this.aoTracks[iGpxIndex].id = asFolder.properties.tracks[iGaiaIndex].id;
|
|
||||||
this.feedback('info', 'Track Color - Track "'+this.aoTracks[iGpxIndex].name+'" found a match ('+(++iCount)+'/'+this.aoTracks.length+')');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: Gaia.API+'/track/'+this.aoTracks[iGpxIndex].id+'/',
|
|
||||||
color: this.aoTracks[iGpxIndex].color
|
|
||||||
}).done(function(asGaiaTrackDisplay) {
|
|
||||||
var asGaiaTrack = asGaiaTrackDisplay.features[0];
|
|
||||||
delete asGaiaTrack.id;
|
|
||||||
delete asGaiaTrack.style;
|
|
||||||
|
|
||||||
//Set color
|
|
||||||
var sColor = '#ff0000';
|
|
||||||
switch(this.color) {
|
|
||||||
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
|
||||||
case 'Magenta': sColor = '#B60DC3'; break;
|
|
||||||
}
|
|
||||||
asGaiaTrack.properties.color = sColor;
|
|
||||||
asGaiaTrack.properties.hexcolor = sColor;
|
|
||||||
|
|
||||||
self.feedback('info', 'Track Color - Setting track color "'+sColor+'" ('+this.color+') to "'+asGaiaTrack.properties.title+'"');
|
|
||||||
$.ajax({
|
|
||||||
url: Gaia.API+'/track/'+asGaiaTrack.properties.id+'/',
|
|
||||||
type: 'PUT',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: JSON.stringify(asGaiaTrack)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uploadWayPoints(iIndex, bSecondTry) {
|
uploadWayPoints(iIndex) {
|
||||||
iIndex = iIndex || 0;
|
iIndex = iIndex || 0;
|
||||||
bSecondTry = bSecondTry || false;
|
|
||||||
|
|
||||||
//Upload waypoints
|
//Upload waypoints
|
||||||
if(iIndex < this.aoWaypoints.length) {
|
var sWaypointName = this.aoWaypoints[iIndex].name;
|
||||||
var sWaypointName = this.aoWaypoints[iIndex].name;
|
|
||||||
|
|
||||||
this.feedback('info', 'Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+sWaypointName+')');
|
this.feedback('info', 'Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+sWaypointName+')');
|
||||||
var asPost = {
|
var asPost = {
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
geometry: {
|
geometry: {
|
||||||
type: 'Point',
|
type: 'Point',
|
||||||
coordinates: [
|
coordinates: [
|
||||||
this.aoWaypoints[iIndex].lon,
|
this.aoWaypoints[iIndex].lon,
|
||||||
this.aoWaypoints[iIndex].lat,
|
this.aoWaypoints[iIndex].lat,
|
||||||
this.aoWaypoints[iIndex].ele
|
this.aoWaypoints[iIndex].ele
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
properties: {
|
properties: {
|
||||||
title: sWaypointName,
|
title: sWaypointName,
|
||||||
time_created: "2020-06-07T14:01:03.944Z",
|
time_created: this.aoWaypoints[iIndex].time,
|
||||||
icon: Gaia.getIconName(this.aoWaypoints[iIndex].sym),
|
icon: Gaia.getIconName(this.aoWaypoints[iIndex].sym),
|
||||||
isValid: true,
|
isValid: true,
|
||||||
isLatestImport: true,
|
isLatestImport: true,
|
||||||
filename: this.aoWaypoints[iIndex].filename,
|
filename: this.aoWaypoints[iIndex].filename,
|
||||||
writable: true,
|
writable: true,
|
||||||
localId: iIndex+'',
|
localId: iIndex+'',
|
||||||
notes: this.aoWaypoints[iIndex].desc,
|
notes: this.aoWaypoints[iIndex].desc,
|
||||||
archived: false,
|
archived: false,
|
||||||
isLocallyCreated: true,
|
isLocallyCreated: true,
|
||||||
type: 'waypoint',
|
type: 'waypoint',
|
||||||
parent_folder_id: this.sFolderId
|
parent_folder_id: this.sFolderId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sData = JSON.stringify(asPost);
|
let sData = JSON.stringify(asPost);
|
||||||
var self = this;
|
var self = this;
|
||||||
$.post({
|
$.post({
|
||||||
url: Gaia.API+'/waypoint/',
|
url: Gaia.API+'/waypoint/',
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: sData,
|
data: sData
|
||||||
postedData: sData
|
}).done(function(asWaypoint) {
|
||||||
}).done(function(asWaypoint) {
|
self.aoWaypoints[iIndex] = asWaypoint;
|
||||||
//Update local waypoint with all server info (including ID)
|
self.confirmWayPoint(iIndex, asWaypoint, this.data);
|
||||||
self.aoWaypoints[iIndex] = asWaypoint;
|
}).fail(function(){
|
||||||
|
self.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' "'+sWaypointName+'" (Stage 1). Trying again...');
|
||||||
|
self.uploadWayPoints(iIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$.ajax({
|
confirmWayPoint(iIndex, asWaypoint, sPostedData) {
|
||||||
url: Gaia.API+'/waypoint/'+asWaypoint.properties.id+'/',
|
$.ajax({
|
||||||
type: 'PUT',
|
url: Gaia.API+'/waypoint/'+asWaypoint.properties.id+'/',
|
||||||
contentType: 'application/json',
|
type: 'PUT',
|
||||||
data: this.postedData
|
contentType: 'application/json',
|
||||||
}).always(() => {
|
data: sPostedData
|
||||||
self.uploadWayPoints(++iIndex);
|
}).done(() => {
|
||||||
});
|
iIndex++;
|
||||||
}).fail(function(){
|
this.incProgress();
|
||||||
self.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' ('+sWaypointName+'). Trying again...');
|
if(iIndex < this.aoWaypoints.length) this.uploadWayPoints(iIndex);
|
||||||
self.uploadWayPoints(iIndex, true);
|
else this.assignElementsToFolder();
|
||||||
});
|
}).fail(() => {
|
||||||
}
|
this.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' "'+asWaypoint.properties.title+'" (Stage 2). Trying again...');
|
||||||
|
this.confirmWayPoint(iIndex, asWaypoint, sPostedData);
|
||||||
//Done uploading, assigning waypoints & tracks to folder
|
});
|
||||||
else this.assignElementsToFolder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assignElementsToFolder() {
|
assignElementsToFolder() {
|
||||||
@@ -735,9 +841,11 @@ class Gaia {
|
|||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: JSON.stringify(asFolder)
|
data: JSON.stringify(asFolder)
|
||||||
}).done(() => {
|
}).done(() => {
|
||||||
|
this.incProgress();
|
||||||
this.feedback('info', 'Done');
|
this.feedback('info', 'Done');
|
||||||
}).fail(() => {
|
}).fail(() => {
|
||||||
this.feedback('error', 'WFailed to assign waypoints & tracks to folder ID "'+asFolder.id+'"');
|
this.feedback('warning', 'Failed to assign waypoints & tracks to folder ID "'+asFolder.id+'". Retrying...');
|
||||||
|
this.assignElementsToFolder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,9 +885,13 @@ class Gaia {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('Loading GaiaGps Uploader...');
|
console.log('Loading GaiaGps Uploader...');
|
||||||
|
let oGaia = new Gaia();
|
||||||
|
|
||||||
//To be adjusted regularly
|
/* To be adjusted on Gaia's updates */
|
||||||
$FileInput = $('input[type=file]')
|
|
||||||
$FileButton = $('a[href="https://help.gaiagps.com/hc/en-us/articles/360052763513"]').parent().find('button');
|
|
||||||
|
|
||||||
let oGaia = new Gaia($FileInput, $FileButton);
|
//Side panel
|
||||||
|
$('path[d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"]').parent().parent().on('click', () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
oGaia.setLayout();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user