Add Gaia upload progress bar
This commit is contained in:
@@ -434,26 +434,57 @@ class Gaia {
|
||||
static get URL() { return 'https://www.gaiagps.com'; }
|
||||
static get API() { return Gaia.URL+'/api/objects'; }
|
||||
|
||||
constructor($InputFile, $InputButton) {
|
||||
constructor() {
|
||||
this.asFiles = [];
|
||||
this.aoWaypoints = [];
|
||||
this.aoTracks = [];
|
||||
this.sFolderId = '';
|
||||
this.asFolder = {};
|
||||
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.$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.progress = {current:0, total:0};
|
||||
}
|
||||
|
||||
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
|
||||
this.$InputFile = $InputFile.clone().insertAfter($InputFile);
|
||||
$InputFile.remove();
|
||||
//If the button is found (=displayed)
|
||||
if($InputButton.length > 0) {
|
||||
this.$InputBox = $InputButton.parent();
|
||||
|
||||
this.$InputButton = $InputButton.clone().insertAfter($InputButton);
|
||||
$InputButton.remove();
|
||||
//Add Feedback box
|
||||
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) {
|
||||
@@ -464,32 +495,45 @@ class Gaia {
|
||||
switch(sType) {
|
||||
case 'error': sColor = 'red'; 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.scrollTop(this.$Feedback.prop("scrollHeight"));
|
||||
}
|
||||
|
||||
//Modify Gaia DOM Interface
|
||||
setLayout() {
|
||||
//Add Feedback box
|
||||
this.$Feedback.appendTo($('body'));
|
||||
incProgress() {
|
||||
if(!this.progress.current) {
|
||||
this.progress.$Done = $('<div>', {'style':'overflow:hidden; background:#2D5E38; color: white; text-align:right;'});
|
||||
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.$InputButton.click(() => {this.$InputFile.click();});
|
||||
this.progress.current++;
|
||||
|
||||
//Set event on file selection
|
||||
this.$InputFile
|
||||
.attr('multiple', 'multiple')
|
||||
.attr('name', 'files[]')
|
||||
.change(() => {this.readInputFiles();});
|
||||
|
||||
//Set default Name
|
||||
this.$InputName.val('PCT').prependTo(this.$InputBox);
|
||||
|
||||
//Clear all upload notifications
|
||||
this.resetNotif();
|
||||
if(this.progress.current < this.progress.total) {
|
||||
let iRatio = Math.round(this.progress.current / this.progress.total * 100);
|
||||
let sTextDone = '', sTextLeft = '';
|
||||
if(iRatio < 50) {
|
||||
sTextDone = '';
|
||||
sTextLeft = ' '+iRatio+'% ('+this.progress.current+' / '+this.progress.total+')';
|
||||
}
|
||||
else {
|
||||
sTextDone = '('+this.progress.current+' / '+this.progress.total+') '+iRatio+'% ';
|
||||
sTextLeft = '';
|
||||
}
|
||||
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
|
||||
@@ -524,7 +568,10 @@ 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.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]);
|
||||
aoReaders[i].readAsText(this.asFiles[i]);
|
||||
@@ -581,94 +628,103 @@ class Gaia {
|
||||
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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//Build & Upload Track File
|
||||
uploadTrack(iIndex, bSecondTry) {
|
||||
uploadTrack(iIndex) {
|
||||
iIndex = iIndex || 0;
|
||||
bSecondTry = bSecondTry || false;
|
||||
|
||||
if(iIndex == 0) this.feedback('info', 'Uploading tracks...');
|
||||
|
||||
if(iIndex < this.aoTracks.length) {
|
||||
let aoTrack = this.aoTracks[i];
|
||||
let aoTrack = this.aoTracks[iIndex];
|
||||
this.feedback('info', 'Uploading track "'+aoTrack.name+'"');
|
||||
|
||||
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
|
||||
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: {
|
||||
type: 'MultiLineString',
|
||||
coordinates: [aoCoords]
|
||||
}
|
||||
});
|
||||
|
||||
var self = this;
|
||||
$.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() {
|
||||
self.feedback('info', 'Track "'+this.trackName+'" uploaded');
|
||||
self.uploadTrack(++iIndex);
|
||||
}).fail(function() {
|
||||
self.feedback('error', 'Track "'+this.trackName+'" failed to upload. Retrying...');
|
||||
self.uploadTrack(iIndex, true);
|
||||
});
|
||||
});
|
||||
//Set color
|
||||
let sColor = '#4ABD32';
|
||||
switch(aoTrack.color) {
|
||||
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
||||
case 'Magenta': sColor = '#B60DC3'; break;
|
||||
}
|
||||
else {
|
||||
self.feedback('info', 'All tracks uploaded');
|
||||
self.uploadWayPoints();
|
||||
|
||||
//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
|
||||
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: {
|
||||
type: 'MultiLineString',
|
||||
coordinates: [aoCoords]
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
confirmTrack(iIndex, asTrack, sPostedData) {
|
||||
iIndex = iIndex || 0;
|
||||
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: Gaia.API+'/track/'+asTrack.features[0].id+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: sPostedData,
|
||||
trackName: asTrack.features[0].properties.title
|
||||
}).done(function() {
|
||||
self.feedback('info', 'Track "'+this.trackName+'" uploaded');
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -694,69 +750,70 @@ class Gaia {
|
||||
}
|
||||
*/
|
||||
|
||||
uploadWayPoints(iIndex, bSecondTry) {
|
||||
uploadWayPoints(iIndex) {
|
||||
iIndex = iIndex || 0;
|
||||
bSecondTry = bSecondTry || false;
|
||||
|
||||
//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+')');
|
||||
var asPost = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [
|
||||
this.aoWaypoints[iIndex].lon,
|
||||
this.aoWaypoints[iIndex].lat,
|
||||
this.aoWaypoints[iIndex].ele
|
||||
]
|
||||
},
|
||||
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
|
||||
}
|
||||
};
|
||||
this.feedback('info', 'Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+sWaypointName+')');
|
||||
var asPost = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [
|
||||
this.aoWaypoints[iIndex].lon,
|
||||
this.aoWaypoints[iIndex].lat,
|
||||
this.aoWaypoints[iIndex].ele
|
||||
]
|
||||
},
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
let sData = JSON.stringify(asPost);
|
||||
var self = this;
|
||||
$.post({
|
||||
url: Gaia.API+'/waypoint/',
|
||||
contentType: 'application/json',
|
||||
data: sData,
|
||||
postedData: sData
|
||||
}).done(function(asWaypoint) {
|
||||
//Update local waypoint with all server info (including ID)
|
||||
self.aoWaypoints[iIndex] = asWaypoint;
|
||||
let sData = JSON.stringify(asPost);
|
||||
var self = this;
|
||||
$.post({
|
||||
url: Gaia.API+'/waypoint/',
|
||||
contentType: 'application/json',
|
||||
data: sData
|
||||
}).done(function(asWaypoint) {
|
||||
self.aoWaypoints[iIndex] = asWaypoint;
|
||||
self.confirmWayPoint(iIndex, asWaypoint, this.data);
|
||||
}).fail(function(){
|
||||
self.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' "'+sWaypointName+'" (Stage 1). Trying again...');
|
||||
self.uploadWayPoints(iIndex);
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: Gaia.API+'/waypoint/'+asWaypoint.properties.id+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: this.postedData
|
||||
}).always(() => {
|
||||
self.uploadWayPoints(++iIndex);
|
||||
});
|
||||
}).fail(function(){
|
||||
self.feedback('error', 'Failed to upload waypoint #'+(iIndex + 1)+' ('+sWaypointName+'). Trying again...');
|
||||
self.uploadWayPoints(iIndex, true);
|
||||
});
|
||||
}
|
||||
|
||||
//Done uploading, assigning waypoints & tracks to folder
|
||||
else this.assignElementsToFolder();
|
||||
confirmWayPoint(iIndex, asWaypoint, sPostedData) {
|
||||
$.ajax({
|
||||
url: Gaia.API+'/waypoint/'+asWaypoint.properties.id+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: sPostedData
|
||||
}).done(() => {
|
||||
iIndex++;
|
||||
this.incProgress();
|
||||
if(iIndex < this.aoWaypoints.length) this.uploadWayPoints(iIndex);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
assignElementsToFolder() {
|
||||
@@ -784,9 +841,11 @@ class Gaia {
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(asFolder)
|
||||
}).done(() => {
|
||||
this.incProgress();
|
||||
this.feedback('info', 'Done');
|
||||
}).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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -826,9 +885,13 @@ class Gaia {
|
||||
}
|
||||
|
||||
console.log('Loading GaiaGps Uploader...');
|
||||
let oGaia = new Gaia();
|
||||
|
||||
//To be adjusted regularly
|
||||
$FileInput = $('input[type=file]');
|
||||
$FileButton = $('a[href="https://help.gaiagps.com/hc/en-us/articles/360052763513"]').parent().find('button');
|
||||
/* To be adjusted on Gaia's updates */
|
||||
|
||||
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