Skip to content

Commit

Permalink
FIX: Remove loading spinner after image export (#477)
Browse files Browse the repository at this point in the history
* FIX: Remove loading spinner after image export

In the old UI, the spinner would continue spinning after the images have been
exported.

Resolves #470

* FIX: Wrap startExport function inside of a promise

* FIX: Add polyfill for ES6 promises

* FIX: Replace arrow function with normal function

Change was necessary because arrow functions are not supported in ES5.

* FIX: Bind this startExport function

The change was necessary because in the Promise the value of
keyword this gets lost
  • Loading branch information
VladimirMikulic authored and jywarren committed Dec 14, 2019
1 parent 1c3aff6 commit af4bea8
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 115 deletions.
125 changes: 67 additions & 58 deletions dist/leaflet.distortableimage.js
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,12 @@ L.ExportAction = L.EditAction.extend({
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner');
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...');
L.IconUtil.addClassToSvg(this._link, 'loader');
edit.startExport();

edit.startExport().then(function() {
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner');
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...');
L.DomUtil.removeClass(this._link.firstChild, 'loader');
}.bind(this));
}
},
});
Expand Down Expand Up @@ -2770,68 +2775,72 @@ L.DistortableCollection.Edit = L.Handler.extend({
},

startExport: function(opts) {
opts = opts || {};
opts.collection = opts.collection || this._group.generateExportJson();
opts.frequency = opts.frequency || 3000;
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel !
var statusUrl;
var updateInterval;

// this may be overridden to update the UI to show export progress or completion
// eslint-disable-next-line require-jsdoc
function _defaultUpdater(data) {
data = JSON.parse(data);
// optimization: fetch status directly from google storage:
if (statusUrl !== data.status_url && data.status_url.match('.json')) {
statusUrl = data.status_url;
}
if (data.status === 'complete') {
clearInterval(updateInterval);
return new Promise(function(resolve) {
opts = opts || {};
opts.collection = opts.collection || this._group.generateExportJson();
opts.frequency = opts.frequency || 3000;
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel !
var statusUrl;
var updateInterval;

// this may be overridden to update the UI to show export progress or completion
// eslint-disable-next-line require-jsdoc
function _defaultUpdater(data) {
data = JSON.parse(data);
// optimization: fetch status directly from google storage:
if (statusUrl !== data.status_url && data.status_url.match('.json')) {
statusUrl = data.status_url;
}
if (data.status === 'complete') {
clearInterval(updateInterval);
resolve();
}
if (data.status === 'complete' && data.jpg !== null) {
alert('Export succeeded. http://export.mapknitter.org/' + data.jpg);
}
// TODO: update to clearInterval when status == "failed" if we update that in this file:
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb
console.log(data);
}
if (data.status === 'complete' && data.jpg !== null) {
alert('Export succeeded. http://export.mapknitter.org/' + data.jpg);

// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json;
// this may be overridden to integrate with any UI
// eslint-disable-next-line require-jsdoc
function _defaultHandleStatusUrl(data) {
console.log(data);
statusUrl = '//export.mapknitter.org' + data;
opts.updater = opts.updater || _defaultUpdater;

// repeatedly fetch the status.json
updateInterval = setInterval(function intervalUpdater() {
$.ajax(statusUrl + '?' + Date.now(), {
// bust cache with timestamp
type: 'GET',
crossDomain: true
}).done(function(data) {
opts.updater(data);
});
}, opts.frequency);
}
// TODO: update to clearInterval when status == "failed" if we update that in this file:
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb
console.log(data);
}

// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json;
// this may be overridden to integrate with any UI
// eslint-disable-next-line require-jsdoc
function _defaultHandleStatusUrl(data) {
console.log(data);
statusUrl = '//export.mapknitter.org' + data;
opts.updater = opts.updater || _defaultUpdater;

// repeatedly fetch the status.json
updateInterval = setInterval(function intervalUpdater() {
$.ajax(statusUrl + '?' + Date.now(), {// bust cache with timestamp
type: 'GET',

// eslint-disable-next-line require-jsdoc
function _fetchStatusUrl(collection, scale) {
opts.handleStatusUrl = opts.handleStatusUrl || _defaultHandleStatusUrl;

$.ajax({
url: '//export.mapknitter.org/export',
crossDomain: true,
}).done(function(data) {
opts.updater(data);
type: 'POST',
data: {
collection: JSON.stringify(collection.images),
scale: scale,
},
success: opts.handleStatusUrl, // this handles the initial response
});
}, opts.frequency);
}

// eslint-disable-next-line require-jsdoc
function _fetchStatusUrl(collection, scale) {
opts.handleStatusUrl = opts.handleStatusUrl || _defaultHandleStatusUrl;

$.ajax({
url: '//export.mapknitter.org/export',
crossDomain: true,
type: 'POST',
data: {
collection: JSON.stringify(collection.images),
scale: scale,
},
success: opts.handleStatusUrl, // this handles the initial response
});
}
}

_fetchStatusUrl(opts.collection, opts.scale);
_fetchStatusUrl(opts.collection, opts.scale);
}.bind(this));
},

_addToolbar: function() {
Expand Down
2 changes: 2 additions & 0 deletions examples/select.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<link rel="stylesheet" href="../node_modules/leaflet/dist/leaflet.css" media="screen" title="no title">
<script src="../node_modules/leaflet-toolbar/dist/leaflet.toolbar.js"></script>
<link href="../node_modules/leaflet-toolbar/dist/leaflet.toolbar.css" rel="stylesheet">
<script src="../node_modules/promise-polyfill/dist/polyfill.min.js"></script>


<!-- for full-res export -->
<script src="../node_modules/jquery/dist/jquery.js"></script>
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"glfx": "0.0.4",
"jquery": "~> 3.4.0",
"leaflet-toolbar": "0.4.0-alpha.2",
"promise-polyfill": "^8.1.3",
"webgl-distort": "0.0.2"
},
"devDependencies": {
Expand Down
116 changes: 60 additions & 56 deletions src/edit/DistortableCollection.Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,68 +192,72 @@ L.DistortableCollection.Edit = L.Handler.extend({
},

startExport: function(opts) {
opts = opts || {};
opts.collection = opts.collection || this._group.generateExportJson();
opts.frequency = opts.frequency || 3000;
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel !
var statusUrl;
var updateInterval;

// this may be overridden to update the UI to show export progress or completion
// eslint-disable-next-line require-jsdoc
function _defaultUpdater(data) {
data = JSON.parse(data);
// optimization: fetch status directly from google storage:
if (statusUrl !== data.status_url && data.status_url.match('.json')) {
statusUrl = data.status_url;
}
if (data.status === 'complete') {
clearInterval(updateInterval);
return new Promise(function(resolve) {
opts = opts || {};
opts.collection = opts.collection || this._group.generateExportJson();
opts.frequency = opts.frequency || 3000;
opts.scale = opts.scale || 100; // switch it to _getAvgCmPerPixel !
var statusUrl;
var updateInterval;

// this may be overridden to update the UI to show export progress or completion
// eslint-disable-next-line require-jsdoc
function _defaultUpdater(data) {
data = JSON.parse(data);
// optimization: fetch status directly from google storage:
if (statusUrl !== data.status_url && data.status_url.match('.json')) {
statusUrl = data.status_url;
}
if (data.status === 'complete') {
clearInterval(updateInterval);
resolve();
}
if (data.status === 'complete' && data.jpg !== null) {
alert('Export succeeded. http://export.mapknitter.org/' + data.jpg);
}
// TODO: update to clearInterval when status == "failed" if we update that in this file:
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb
console.log(data);
}
if (data.status === 'complete' && data.jpg !== null) {
alert('Export succeeded. http://export.mapknitter.org/' + data.jpg);

// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json;
// this may be overridden to integrate with any UI
// eslint-disable-next-line require-jsdoc
function _defaultHandleStatusUrl(data) {
console.log(data);
statusUrl = '//export.mapknitter.org' + data;
opts.updater = opts.updater || _defaultUpdater;

// repeatedly fetch the status.json
updateInterval = setInterval(function intervalUpdater() {
$.ajax(statusUrl + '?' + Date.now(), {
// bust cache with timestamp
type: 'GET',
crossDomain: true
}).done(function(data) {
opts.updater(data);
});
}, opts.frequency);
}
// TODO: update to clearInterval when status == "failed" if we update that in this file:
// https://github.com/publiclab/mapknitter-exporter/blob/main/lib/mapknitterExporter.rb
console.log(data);
}

// receives the URL of status.json, and starts running the updater to repeatedly fetch from status.json;
// this may be overridden to integrate with any UI
// eslint-disable-next-line require-jsdoc
function _defaultHandleStatusUrl(data) {
console.log(data);
statusUrl = '//export.mapknitter.org' + data;
opts.updater = opts.updater || _defaultUpdater;

// repeatedly fetch the status.json
updateInterval = setInterval(function intervalUpdater() {
$.ajax(statusUrl + '?' + Date.now(), {// bust cache with timestamp
type: 'GET',
// eslint-disable-next-line require-jsdoc
function _fetchStatusUrl(collection, scale) {
opts.handleStatusUrl = opts.handleStatusUrl || _defaultHandleStatusUrl;

$.ajax({
url: '//export.mapknitter.org/export',
crossDomain: true,
}).done(function(data) {
opts.updater(data);
type: 'POST',
data: {
collection: JSON.stringify(collection.images),
scale: scale,
},
success: opts.handleStatusUrl, // this handles the initial response
});
}, opts.frequency);
}

// eslint-disable-next-line require-jsdoc
function _fetchStatusUrl(collection, scale) {
opts.handleStatusUrl = opts.handleStatusUrl || _defaultHandleStatusUrl;

$.ajax({
url: '//export.mapknitter.org/export',
crossDomain: true,
type: 'POST',
data: {
collection: JSON.stringify(collection.images),
scale: scale,
},
success: opts.handleStatusUrl, // this handles the initial response
});
}
}

_fetchStatusUrl(opts.collection, opts.scale);
_fetchStatusUrl(opts.collection, opts.scale);
}.bind(this));
},

_addToolbar: function() {
Expand Down
7 changes: 6 additions & 1 deletion src/edit/actions/ExportAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ L.ExportAction = L.EditAction.extend({
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner');
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...');
L.IconUtil.addClassToSvg(this._link, 'loader');
edit.startExport();

edit.startExport().then(function() {
L.IconUtil.toggleXlink(this._link, 'get_app', 'spinner');
L.IconUtil.toggleTitle(this._link, 'Export Images', 'Loading...');
L.DomUtil.removeClass(this._link.firstChild, 'loader');
}.bind(this));
}
},
});

0 comments on commit af4bea8

Please sign in to comment.