Gaia updater v3.1
This commit is contained in:
567
gaia/upload.js
567
gaia/upload.js
@@ -1,20 +1,27 @@
|
||||
// ==UserScript==
|
||||
// @name GaiaGps Uploader
|
||||
// @description Allow the user to upload multiple files at once and more than 1000 waypoints
|
||||
// @version 3.0
|
||||
// @grant none
|
||||
// @match https://www.gaiagps.com/map/*
|
||||
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.5.0/jquery.min.js
|
||||
// @namespace https://greasyfork.org/users/583371
|
||||
// @description Allow the user to upload multiple files at once and more than 1000 waypoints
|
||||
// @grant none
|
||||
// @version 3.1
|
||||
// @author Franzz
|
||||
// @match https://www.gaiagps.com/map/*
|
||||
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
|
||||
// ==/UserScript==
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
//Ctrl+Alt+Shift+I to open network tab on addon
|
||||
|
||||
/* GPXParser - v3.0.6 - https://github.com/Luuka/GPXParser.js/blob/master/src/GPXParser.js */
|
||||
/* GPXParser - v3.0.8 - https://github.com/Luuka/GPXParser.js/blob/master/src/GPXParser.js */
|
||||
/* Personnal modifications have been applied, care on upgrade */
|
||||
let gpxParser = function () {
|
||||
|
||||
/**
|
||||
* GPX file parser
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
let gpxParser = function () {
|
||||
this.xmlSource = "";
|
||||
this.metadata = {};
|
||||
this.waypoints = [];
|
||||
@@ -22,13 +29,20 @@ let gpxParser = function () {
|
||||
this.routes = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a gpx formatted string to a GPXParser Object
|
||||
*
|
||||
* @param {string} gpxstring - A GPX formatted String
|
||||
*
|
||||
* @return {gpxParser} A GPXParser object
|
||||
*/
|
||||
gpxParser.prototype.parse = function (gpxstring) {
|
||||
let keepThis = this;
|
||||
|
||||
let domParser = new window.DOMParser();
|
||||
this.xmlSource = domParser.parseFromString(gpxstring, 'text/xml');
|
||||
|
||||
metadata = this.xmlSource.querySelector('metadata');
|
||||
let metadata = this.xmlSource.querySelector('metadata');
|
||||
if(metadata != null){
|
||||
this.metadata.name = this.getElementValue(metadata, "name");
|
||||
this.metadata.desc = this.getElementValue(metadata, "desc");
|
||||
@@ -70,9 +84,11 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
for (let idx in wpts){
|
||||
var wpt = wpts[idx];
|
||||
let pt = {};
|
||||
pt.name = keepThis.getElementValue(wpt, "name")
|
||||
pt.name = keepThis.getElementValue(wpt, "name");
|
||||
pt.lat = parseFloat(wpt.getAttribute("lat"));
|
||||
pt.lon = parseFloat(wpt.getAttribute("lon"));
|
||||
//let floatValue = parseFloat(keepThis.getElementValue(wpt, "ele"));
|
||||
//pt.ele = isNaN(floatValue) ? null : floatValue;
|
||||
pt.ele = parseFloat(keepThis.getElementValue(wpt, "ele")) || null;
|
||||
pt.cmt = keepThis.getElementValue(wpt, "cmt");
|
||||
pt.desc = keepThis.getElementValue(wpt, "desc");
|
||||
@@ -80,7 +96,7 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
|
||||
//let time = keepThis.getElementValue(wpt, "time");
|
||||
//pt.time = time == null ? null : new Date(time);
|
||||
pt.time = (keepThis.getElementValue(wpt, "time") || keepThis.metadata.time) || null;;
|
||||
pt.time = (keepThis.getElementValue(wpt, "time") || keepThis.metadata.time) || null;
|
||||
|
||||
keepThis.waypoints.push(pt);
|
||||
}
|
||||
@@ -115,6 +131,8 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
let pt = {};
|
||||
pt.lat = parseFloat(rtept.getAttribute("lat"));
|
||||
pt.lon = parseFloat(rtept.getAttribute("lon"));
|
||||
//let floatValue = parseFloat(keepThis.getElementValue(rtept, "ele"));
|
||||
//pt.ele = isNaN(floatValue) ? null : floatValue;
|
||||
pt.ele = parseFloat(keepThis.getElementValue(rtept, "ele")) || null;
|
||||
|
||||
//let time = keepThis.getElementValue(rtept, "time");
|
||||
@@ -127,7 +145,7 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
//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);
|
||||
}
|
||||
@@ -159,11 +177,13 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
|
||||
let trackpoints = [];
|
||||
let trkpts = [].slice.call(trk.querySelectorAll('trkpt'));
|
||||
for (let idxIn in trkpts){
|
||||
for (let idxIn in trkpts){
|
||||
var trkpt = trkpts[idxIn];
|
||||
let pt = {};
|
||||
pt.lat = parseFloat(trkpt.getAttribute("lat"));
|
||||
pt.lon = parseFloat(trkpt.getAttribute("lon"));
|
||||
//let floatValue = parseFloat(keepThis.getElementValue(trkpt, "ele"));
|
||||
//pt.ele = isNaN(floatValue) ? null : floatValue;
|
||||
pt.ele = parseFloat(keepThis.getElementValue(trkpt, "ele")) || null;
|
||||
|
||||
//let time = keepThis.getElementValue(trkpt, "time");
|
||||
@@ -175,20 +195,37 @@ gpxParser.prototype.parse = function (gpxstring) {
|
||||
//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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get value from a XML DOM element
|
||||
*
|
||||
* @param {Element} parent - Parent DOM Element
|
||||
* @param {string} needle - Name of the searched element
|
||||
*
|
||||
* @return {} The element value
|
||||
*/
|
||||
gpxParser.prototype.getElementValue = function(parent, needle){
|
||||
let elem = parent.querySelector(needle);
|
||||
if(elem != null){
|
||||
return $('<div>').html(elem.innerHTML != undefined ? elem.innerHTML : elem.childNodes[0].data).text();
|
||||
return elem.innerHTML != undefined ? elem.innerHTML : elem.childNodes[0].data;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Search the value of a direct child XML DOM element
|
||||
*
|
||||
* @param {Element} parent - Parent DOM Element
|
||||
* @param {string} needle - Name of the searched element
|
||||
*
|
||||
* @return {} The element value
|
||||
*/
|
||||
gpxParser.prototype.queryDirectSelector = function(parent, needle) {
|
||||
|
||||
let elements = parent.querySelectorAll(needle);
|
||||
@@ -206,232 +243,8 @@ gpxParser.prototype.queryDirectSelector = function(parent, needle) {
|
||||
}
|
||||
|
||||
return finalElem;
|
||||
}
|
||||
|
||||
/*
|
||||
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 () {
|
||||
var GeoJSON = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [],
|
||||
"properties": {
|
||||
"name": this.metadata.name,
|
||||
"desc": this.metadata.desc,
|
||||
"time": this.metadata.time,
|
||||
"author": this.metadata.author,
|
||||
"link": this.metadata.link,
|
||||
},
|
||||
};
|
||||
|
||||
for(idx in this.tracks) {
|
||||
let track = this.tracks[idx];
|
||||
|
||||
var feature = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": []
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
};
|
||||
|
||||
feature.properties.name = track.name;
|
||||
feature.properties.cmt = track.cmt;
|
||||
feature.properties.desc = track.desc;
|
||||
feature.properties.src = track.src;
|
||||
feature.properties.number = track.number;
|
||||
feature.properties.link = track.link;
|
||||
feature.properties.type = track.type;
|
||||
|
||||
for(idx in track.points) {
|
||||
let pt = track.points[idx];
|
||||
|
||||
var geoPt = [];
|
||||
geoPt.push(pt.lon);
|
||||
geoPt.push(pt.lat);
|
||||
geoPt.push(pt.ele);
|
||||
|
||||
feature.geometry.coordinates.push(geoPt);
|
||||
}
|
||||
|
||||
GeoJSON.features.push(feature);
|
||||
}
|
||||
|
||||
for(idx in this.routes) {
|
||||
let track = this.routes[idx];
|
||||
|
||||
var feature = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": []
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
};
|
||||
|
||||
feature.properties.name = track.name;
|
||||
feature.properties.cmt = track.cmt;
|
||||
feature.properties.desc = track.desc;
|
||||
feature.properties.src = track.src;
|
||||
feature.properties.number = track.number;
|
||||
feature.properties.link = track.link;
|
||||
feature.properties.type = track.type;
|
||||
|
||||
|
||||
for(idx in track.points) {
|
||||
let pt = track.points[idx];
|
||||
|
||||
var geoPt = [];
|
||||
geoPt.push(pt.lon);
|
||||
geoPt.push(pt.lat);
|
||||
geoPt.push(pt.ele);
|
||||
|
||||
feature.geometry.coordinates.push(geoPt);
|
||||
}
|
||||
|
||||
GeoJSON.features.push(feature);
|
||||
}
|
||||
|
||||
for(idx in this.waypoints) {
|
||||
let pt = this.waypoints[idx];
|
||||
|
||||
var feature = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": []
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
};
|
||||
|
||||
feature.properties.name = pt.name;
|
||||
feature.properties.cmt = pt.cmt;
|
||||
feature.properties.desc = pt.desc;
|
||||
|
||||
feature.geometry.coordinates = [pt.lon, pt.lat, pt.ele];
|
||||
|
||||
GeoJSON.features.push(feature);
|
||||
}
|
||||
|
||||
return GeoJSON;
|
||||
}
|
||||
|
||||
if(typeof module !== 'undefined'){
|
||||
require('jsdom-global')();
|
||||
module.exports = gpxParser;
|
||||
}
|
||||
|
||||
gpxParser.prototype.getGPX = function(sName) {
|
||||
var sTrack = '';
|
||||
|
||||
for(var i=0 ; i < this.tracks.length ; i++) {
|
||||
var sTrkSeg = '';
|
||||
for(var j=0 ; j < this.tracks[i].points.length ; j++) {
|
||||
sTrkSeg += '<trkpt lat="'+this.tracks[i].points[j].lat+'" lon="'+this.tracks[i].points[j].lon+'">'+
|
||||
'<ele>'+(this.tracks[i].points[j].ele || '')+'</ele>'+
|
||||
'</trkpt>';
|
||||
}
|
||||
sTrack += '<trk>'+
|
||||
'<name>'+(this.tracks[i].name || '')+'</name>'+
|
||||
'<desc>'+(this.tracks[i].desc || '')+'</desc>'+
|
||||
'<src>'+(this.tracks[i].src || '')+'</src>'+
|
||||
'<trkseg>'+sTrkSeg+'</trkseg>'+
|
||||
'</trk>';
|
||||
}
|
||||
|
||||
var sGPX = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'+
|
||||
'<gpx version="1.1" creator="Franzz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">'+
|
||||
'<metadata><name>'+sName+'</name></metadata>'+
|
||||
sTrack+
|
||||
'</gpx>';
|
||||
|
||||
return sGPX;
|
||||
};
|
||||
*/
|
||||
|
||||
class Gaia {
|
||||
static get URL() { return 'https://www.gaiagps.com'; }
|
||||
@@ -441,26 +254,26 @@ class Gaia {
|
||||
this.asFiles = [];
|
||||
this.aoWaypoints = [];
|
||||
this.aoTracks = [];
|
||||
this.sFolderId = '';
|
||||
this.asFolder = {};
|
||||
this.sFolderName = '';
|
||||
this.asFolders = {};
|
||||
this.progress = {current:0, total:0};
|
||||
}
|
||||
|
||||
/* FIXME: adapts on GaiaGPS upgrade */
|
||||
setLayout() {
|
||||
|
||||
/* FIXME: adapts on GaiaGPS upgrade */
|
||||
let $InputButton = $('a[href="https://help.gaiagps.com/hc/en-us/articles/360052763513"]').parent().find('button');
|
||||
|
||||
//If the button is found (=displayed)
|
||||
if($InputButton.length > 0) {
|
||||
this.$InputBox = $InputButton.parent();
|
||||
this.$InputBox = $InputButton.parent();
|
||||
|
||||
//Add Feedback box
|
||||
this.$Feedback = ($('#ggu-feedback').length > 0)?$('#ggu-feedback'):($('<div>', {
|
||||
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));
|
||||
|
||||
/*
|
||||
//Add Folder Name Input next to button
|
||||
this.$InputName = ($('#ggu-inputname').length > 0)?$('#ggu-inputname'):($('<input>', {
|
||||
'type':'text',
|
||||
@@ -469,8 +282,9 @@ class Gaia {
|
||||
'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
|
||||
*/
|
||||
|
||||
//Reset File Input DOM Element
|
||||
let $InputFile = $('input[type=file]');
|
||||
this.$InputFile = $InputFile.clone()
|
||||
.insertAfter($InputFile)
|
||||
@@ -560,7 +374,6 @@ class Gaia {
|
||||
else this.feedback('info', 'Parsing input files');
|
||||
|
||||
//Get Folder Name (text input)
|
||||
this.sFolderName = this.$InputName.val();
|
||||
let aoReaders = [];
|
||||
let iCount = 0;
|
||||
this.asFiles = this.$InputFile.prop('files');
|
||||
@@ -571,16 +384,18 @@ class Gaia {
|
||||
iCount++;
|
||||
this.feedback('info', 'Reading file "'+oFileReader.name+'" ('+iCount+'/'+this.asFiles.length+')');
|
||||
this.parseFile(oFileReader.name, asResult.target.result);
|
||||
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.asFolders[oFileReader.name] = {};
|
||||
|
||||
if(iCount == this.asFiles.length) {
|
||||
this.progress.total = this.aoTracks.length + this.aoWaypoints.length + this.asFiles.length * 2; //2 extra actions per file: Create folder + Assign objects to folder
|
||||
this.createFolders();
|
||||
}
|
||||
};
|
||||
})(this.asFiles[i]);
|
||||
aoReaders[i].readAsText(this.asFiles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Parse GPX files to consolidate tracks & waypoints
|
||||
parseFile(sFileName, oContent) {
|
||||
this.feedback('info', 'Parsing file "'+sFileName+'"');
|
||||
@@ -591,8 +406,8 @@ class Gaia {
|
||||
//Waypoints
|
||||
for(var w in oGPX.waypoints) {
|
||||
oGPX.waypoints[w].filename = sFileName;
|
||||
/*var sWaypointName = oGPX.waypoints[w].name;
|
||||
if(sWaypointName.indexOf('Milestone - ') != -1 && sWaypointName.substr(-2) != '00') { //1 milestone every 100 miles
|
||||
var sWaypointName = oGPX.waypoints[w].name;
|
||||
/* if(sWaypointName.indexOf('Milestone - ') != -1 && sWaypointName.substr(-2) != '00') { //1 milestone every 100 miles
|
||||
this.feedback('info', 'Ignoring milestone waypoint "'+sWaypointName+'"');
|
||||
}
|
||||
else */this.aoWaypoints.push(oGPX.waypoints[w]);
|
||||
@@ -606,37 +421,47 @@ class Gaia {
|
||||
}
|
||||
|
||||
//Delete existing folder with same name & recreating it
|
||||
createFolder() {
|
||||
this.feedback('info', 'Looking for existing folder "'+this.sFolderName+'"...');
|
||||
createFolders() {
|
||||
let iCount = 0;
|
||||
$.each(this.asFolders, (sFileName, asFolder) => {
|
||||
|
||||
$.get(Gaia.API+'/folder/?search='+this.sFolderName).done((asFolders) => {
|
||||
if(asFolders != '' && !$.isEmptyObject(asFolders)) {
|
||||
for(var f in asFolders) {
|
||||
this.feedback('info', 'Deleting "'+asFolders[f].title+'" folder');
|
||||
$.ajax({
|
||||
url: Gaia.API+'/folder/'+asFolders[f].id+'/',
|
||||
type: 'DELETE'
|
||||
});
|
||||
}
|
||||
}
|
||||
else this.feedback('info', 'No folder named "'+this.sFolderName+'" found');
|
||||
//Folder Name
|
||||
let sFolderName = sFileName.replace(/\.[^\.]+$/, '');
|
||||
|
||||
this.feedback('info', 'Looking for existing folder "'+sFolderName+'"...');
|
||||
$.get(Gaia.API+'/folder/?search='+sFolderName).done((asFolders) => {
|
||||
if(asFolders != '' && !$.isEmptyObject(asFolders)) {
|
||||
for(var f in asFolders) {
|
||||
this.feedback('info', 'Deleting "'+asFolders[f].title+'" folder');
|
||||
$.ajax({
|
||||
url: Gaia.API+'/folder/'+asFolders[f].id+'/',
|
||||
type: 'DELETE'
|
||||
});
|
||||
}
|
||||
}
|
||||
else this.feedback('info', 'No folder named "'+sFolderName+'" found');
|
||||
|
||||
this.feedback('info', 'Creating folder "'+this.sFolderName+'"');
|
||||
$.post({
|
||||
url: Gaia.API+'/folder/',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({imported: true, title: this.sFolderName})
|
||||
}).done((asFolder) => {
|
||||
this.feedback('info', 'Folder "'+asFolder.properties.name+'" created');
|
||||
this.asFolder = asFolder;
|
||||
this.sFolderId = asFolder.id;
|
||||
this.sFolderName = asFolder.properties.name;
|
||||
this.incProgress();
|
||||
this.uploadTrack();
|
||||
}).fail(() => {
|
||||
this.feedback('error', 'Folder "'+this.sFolderName+'" could not be created');
|
||||
});
|
||||
});
|
||||
this.feedback('info', 'Creating folder "'+sFolderName+'"');
|
||||
let sTime = (new Date()).toISOString();
|
||||
$.post({
|
||||
url: Gaia.API+'/folder/',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
title: sFolderName,
|
||||
imported: true
|
||||
})
|
||||
}).done((asFolder) => {
|
||||
this.feedback('info', 'Folder "'+asFolder.properties.name+'" created');
|
||||
this.asFolders[sFileName] = asFolder;
|
||||
this.incProgress();
|
||||
|
||||
iCount++;
|
||||
if(iCount == Object.keys(this.asFolders).length) this.uploadTrack();
|
||||
}).fail(() => {
|
||||
this.feedback('error', 'Folder "'+sFolderName+'" could not be created');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//Build & Upload Track File
|
||||
@@ -648,13 +473,14 @@ class Gaia {
|
||||
let aoTrack = this.aoTracks[iIndex];
|
||||
this.feedback('info', 'Uploading track "'+aoTrack.name+'"');
|
||||
|
||||
//Set color: Convert Garmin Colors
|
||||
let sColor = '#4ABD32';
|
||||
switch(aoTrack.color) {
|
||||
case 'DarkBlue': sColor = '#2D3FC7'; break; //Personal Color
|
||||
case 'Magenta': sColor = '#B60DC3'; break; //Personal Color
|
||||
|
||||
//Garmin Colors
|
||||
|
||||
//Personal Colors
|
||||
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
||||
case 'Magenta': sColor = '#B60DC3'; break;
|
||||
|
||||
//Garmin Colors
|
||||
case 'Black': sColor = '#000000'; break;
|
||||
case 'DarkRed': sColor = '#F90553'; break;
|
||||
case 'DarkGreen': sColor = '#009B89'; break;
|
||||
@@ -668,7 +494,7 @@ class Gaia {
|
||||
case 'Green': sColor = '#36C03B'; break;
|
||||
case 'Yellow': sColor = '#FFF011'; break;
|
||||
case 'Blue': sColor = '#2D3FC7'; break;
|
||||
//case 'Magenta': sColor = '#B60DC3'; break;
|
||||
//case 'Magenta': sColor = '#B60DC3'; break;
|
||||
case 'Cyan': sColor = '#00C3DD'; break;
|
||||
case 'White': sColor = '#FFFFFF'; break;
|
||||
case 'Transparent': sColor = '#784D3E'; break;
|
||||
@@ -683,30 +509,30 @@ class Gaia {
|
||||
|
||||
//Convert to geojson
|
||||
let sPostedData = JSON.stringify({
|
||||
type: 'feature',
|
||||
properties: {
|
||||
color: sColor,
|
||||
title: aoTrack.name,
|
||||
time_created: aoTrack.time,
|
||||
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: {
|
||||
coordinates: [aoCoords],
|
||||
type: 'MultiLineString'
|
||||
},
|
||||
geometry: {
|
||||
type: 'MultiLineString',
|
||||
coordinates: [aoCoords]
|
||||
}
|
||||
properties: {
|
||||
archived: false,
|
||||
color: sColor,
|
||||
//distance: 168405.62350073704,
|
||||
filename: aoTrack.filename,
|
||||
hexcolor: sColor,
|
||||
isLatestImport: true,
|
||||
isLocallyCreated: true,
|
||||
isPublicTrack: false,
|
||||
isValid: true,
|
||||
localId: 'track'+(iIndex + 1),
|
||||
notes: aoTrack.desc,
|
||||
parent_folder_id: this.asFolders[aoTrack.filename].id,
|
||||
routing_mode: null,
|
||||
time_created: aoTrack.time || (new Date()).toISOString(),
|
||||
title: aoTrack.name,
|
||||
type: 'track',
|
||||
writable: true
|
||||
},
|
||||
type: 'Feature'
|
||||
});
|
||||
|
||||
var self = this;
|
||||
@@ -777,33 +603,34 @@ class Gaia {
|
||||
|
||||
//Upload waypoints
|
||||
var sWaypointName = this.aoWaypoints[iIndex].name;
|
||||
var aoWaypoint = this.aoWaypoints[iIndex];
|
||||
|
||||
this.feedback('info', 'Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+sWaypointName+')');
|
||||
this.feedback('info', 'Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+aoWaypoint.name+')');
|
||||
var asPost = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [
|
||||
this.aoWaypoints[iIndex].lon,
|
||||
this.aoWaypoints[iIndex].lat,
|
||||
this.aoWaypoints[iIndex].ele
|
||||
]
|
||||
aoWaypoint.lon,
|
||||
aoWaypoint.lat,
|
||||
aoWaypoint.ele
|
||||
],
|
||||
type: 'Point'
|
||||
},
|
||||
properties: {
|
||||
title: sWaypointName,
|
||||
time_created: this.aoWaypoints[iIndex].time,
|
||||
icon: Gaia.getIconName(this.aoWaypoints[iIndex].sym),
|
||||
isValid: true,
|
||||
isLatestImport: true,
|
||||
filename: this.aoWaypoints[iIndex].filename,
|
||||
writable: true,
|
||||
localId: iIndex+'',
|
||||
notes: this.aoWaypoints[iIndex].desc,
|
||||
archived: false,
|
||||
isLocallyCreated: true,
|
||||
type: 'waypoint',
|
||||
parent_folder_id: this.sFolderId
|
||||
}
|
||||
archived: false,
|
||||
filename: aoWaypoint.filename,
|
||||
icon: Gaia.getIconName(aoWaypoint.sym),
|
||||
isLatestImport: true,
|
||||
isLocallyCreated: true,
|
||||
isValid: true,
|
||||
localId: iIndex+'',
|
||||
notes: aoWaypoint.desc,
|
||||
parent_folder_id: this.asFolders[aoWaypoint.filename].id,
|
||||
time_created: aoWaypoint.time || (new Date()).toISOString(),
|
||||
title: aoWaypoint.name,
|
||||
type: 'waypoint',
|
||||
writable: true
|
||||
},
|
||||
type: 'Feature'
|
||||
};
|
||||
|
||||
let sData = JSON.stringify(asPost);
|
||||
@@ -831,43 +658,56 @@ class Gaia {
|
||||
iIndex++;
|
||||
this.incProgress();
|
||||
if(iIndex < this.aoWaypoints.length) this.uploadWayPoints(iIndex);
|
||||
else this.assignElementsToFolder();
|
||||
else this.assignElementsToFolders();
|
||||
}).fail(() => {
|
||||
this.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' "'+asWaypoint.properties.title+'" (Stage 2). Trying again...');
|
||||
this.confirmWayPoint(iIndex, asWaypoint, sPostedData);
|
||||
});
|
||||
}
|
||||
|
||||
assignElementsToFolder() {
|
||||
this.feedback('info', 'Assigning all elements to folder "'+this.asFolder.properties.name+'"');
|
||||
assignElementsToFolders(iIndex) {
|
||||
iIndex = iIndex || 0;
|
||||
let asFolders = Object.keys(this.asFolders).map(key => this.asFolders[key]);
|
||||
let asFolder = asFolders[iIndex];
|
||||
|
||||
let asFolder = {
|
||||
cover_photo_id: this.asFolder.properties.cover_photo_id,
|
||||
id: this.asFolder.id,
|
||||
name: this.asFolder.properties.name,
|
||||
notes: this.asFolder.properties.notes,
|
||||
time_created: this.asFolder.properties.time_created,
|
||||
updated_date: this.asFolder.properties.updated_date
|
||||
this.feedback('info', 'Assigning elements of folder "'+asFolder.properties.name+'"');
|
||||
|
||||
//Folder metadata
|
||||
let asData = {
|
||||
cover_photo_id: asFolder.properties.cover_photo_id,
|
||||
id: asFolder.id,
|
||||
name: asFolder.properties.name,
|
||||
notes: asFolder.properties.notes,
|
||||
time_created: asFolder.properties.time_created,
|
||||
updated_date: asFolder.properties.updated_date
|
||||
}
|
||||
|
||||
//Assign waypoints to folder
|
||||
asFolder.waypoints = [];
|
||||
for(var w in this.aoWaypoints) asFolder.waypoints.push(this.aoWaypoints[w].properties.id);
|
||||
|
||||
asData.waypoints = [];
|
||||
for(var w in this.aoWaypoints) {
|
||||
if(this.aoWaypoints[w].parent_folder_id = asFolder.id) asData.waypoints.push(this.aoWaypoints[w].properties.id);
|
||||
}
|
||||
|
||||
//Assign tracks to folder
|
||||
asFolder.tracks = [];
|
||||
for(var t in this.aoTracks) asFolder.tracks.push(this.aoTracks[t].features[0].id);
|
||||
asData.tracks = [];
|
||||
for(var t in this.aoTracks) {
|
||||
if(this.aoTracks[t].parent_folder_id = asFolder.id) asData.tracks.push(this.aoTracks[t].features[0].id);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: Gaia.API+'/folder/'+asFolder.id+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(asFolder)
|
||||
data: JSON.stringify(asData)
|
||||
}).done(() => {
|
||||
iIndex++;
|
||||
this.incProgress();
|
||||
this.feedback('info', 'Done');
|
||||
this.feedback('info', 'Tracks & waypoints assigned to folder "'+asFolder.properties.name+'"');
|
||||
if(iIndex < asFolders.length) this.assignElementsToFolders(iIndex);
|
||||
else this.feedback('info', 'Done');
|
||||
}).fail(() => {
|
||||
this.feedback('warning', 'Failed to assign waypoints & tracks to folder ID "'+asFolder.id+'". Retrying...');
|
||||
this.assignElementsToFolder();
|
||||
this.feedback('warning', 'Failed to assign waypoints & tracks to folder "'+asFolder.properties.name+'". Trying again...');
|
||||
this.assignElementsToFolders(iIndex);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -906,14 +746,23 @@ class Gaia {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Loading GaiaGps Uploader...');
|
||||
console.log('Loading GaiaGps Uploader 3.1');
|
||||
let oGaia = new Gaia();
|
||||
|
||||
/* To be adjusted on Gaia's updates */
|
||||
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
||||
|
||||
//Side panel
|
||||
$('path[d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"]').parent().parent().on('click', () => {
|
||||
setTimeout(() => {
|
||||
oGaia.setLayout();
|
||||
}, 500);
|
||||
let observer = new MutationObserver((mutations, observer) => {
|
||||
|
||||
/* FIXME: adapts on GaiaGPS upgrade */
|
||||
let $Import = $('div[aria-label="Import Data"]');
|
||||
if($Import.length > 0) {
|
||||
observer.disconnect();
|
||||
$Import.parent('li').on('click', () => { setTimeout(() => { oGaia.setLayout(); }, 500)});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
observer.observe(document, {
|
||||
subtree: true,
|
||||
attributes: true
|
||||
});
|
||||
Reference in New Issue
Block a user