From 8e266c31933343437d8edef3d42f80b50e7e6279 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 28 Feb 2019 23:10:08 +0100 Subject: [PATCH] UI: Fix race in update issue labels and assignees (#6194) Fix #6191 * fix issue update race condition * fix similar race same race when clearing assignee * always load promise polyfill * replace es6-promise with promise-polyfill * move promise-polyfill to --- public/js/index.js | 57 ++++++++++--------- public/vendor/librejs.html | 6 +- .../es6-promise/es6-promise.auto.min.js | 1 - .../plugins/promise-polyfill/polyfill.min.js | 1 + templates/base/footer.tmpl | 1 - templates/base/head.tmpl | 1 + 6 files changed, 35 insertions(+), 32 deletions(-) delete mode 100644 public/vendor/plugins/es6-promise/es6-promise.auto.min.js create mode 100644 public/vendor/plugins/promise-polyfill/polyfill.min.js diff --git a/public/js/index.js b/public/js/index.js index c86ccd4cf0..a34904abba 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -216,17 +216,19 @@ function initBranchSelector() { }); } -function updateIssuesMeta(url, action, issueIds, elementId, afterSuccess) { - $.ajax({ - type: "POST", - url: url, - data: { - "_csrf": csrf, - "action": action, - "issue_ids": issueIds, - "id": elementId - }, - success: afterSuccess +function updateIssuesMeta(url, action, issueIds, elementId) { + return new Promise(function(resolve) { + $.ajax({ + type: "POST", + url: url, + data: { + "_csrf": csrf, + "action": action, + "issue_ids": issueIds, + "id": elementId + }, + success: resolve + }) }) } @@ -348,6 +350,10 @@ function uploadFile(file, callback) { xhr.send(formData); } +function reload() { + window.location.reload(); +} + function initImagePaste(target) { target.each(function(i, field) { field.addEventListener('paste', function(event){ @@ -385,18 +391,20 @@ function initCommentForm() { $('.' + selector).dropdown('setting', 'onHide', function(){ hasLabelUpdateAction = $listMenu.data('action') == 'update'; // Update the var if (hasLabelUpdateAction) { + var promises = []; for (var elementId in labels) { if (labels.hasOwnProperty(elementId)) { var label = labels[elementId]; - updateIssuesMeta( + var promise = updateIssuesMeta( label["update-url"], label["action"], label["issue-id"], elementId ); + promises.push(promise); } } - location.reload(); + Promise.all(promises).then(reload); } }); @@ -479,8 +487,7 @@ function initCommentForm() { "clear", $listMenu.data('issue-id'), "" - ); - $listMenu.data('action', 'update'); // Update to reload the page when we updated items + ).then(reload); } $(this).parent().find('.item').each(function () { @@ -518,9 +525,8 @@ function initCommentForm() { $menu.data('update-url'), "", $menu.data('issue-id'), - $(this).data('id'), - function() { location.reload(); } - ); + $(this).data('id') + ).then(reload); } switch (input_id) { case '#milestone_id': @@ -545,9 +551,8 @@ function initCommentForm() { $menu.data('update-url'), "", $menu.data('issue-id'), - $(this).data('id'), - function() { location.reload(); } - ); + $(this).data('id') + ).then(reload); } $list.find('.selected').html(''); @@ -801,7 +806,7 @@ function initRepository() { function (data) { $editInput.val(data.title); $issueTitle.text(data.title); - location.reload(); + reload(); }); return false; }); @@ -1786,7 +1791,7 @@ function u2fRegistered(resp) { data: JSON.stringify(resp), contentType: "application/json; charset=utf-8", success: function(){ - window.location.reload(); + reload(); }, fail: function (xhr, textStatus) { u2fError(1); @@ -2073,9 +2078,7 @@ $(document).ready(function () { return this.dataset.issueId; }).get().join(); var url = this.dataset.url - updateIssuesMeta(url, action, issueIDs, elementId, function() { - location.reload(); - }); + updateIssuesMeta(url, action, issueIDs, elementId).then(reload); }); buttonsClickOnEnter(); @@ -2912,7 +2915,7 @@ function updateDeadline(deadlineString) { contentType: 'application/json', type: 'POST', success: function () { - window.location.reload(); + reload(); }, error: function () { $('#deadline-loader').removeClass('loading'); diff --git a/public/vendor/librejs.html b/public/vendor/librejs.html index 18c5aca935..1472849661 100644 --- a/public/vendor/librejs.html +++ b/public/vendor/librejs.html @@ -146,9 +146,9 @@ 0.4.1.tar.gz - es6-promise - MIT - 4.2.6.tar.gz + promise-polyfill + MIT + 8.1.0.tar.gz diff --git a/public/vendor/plugins/es6-promise/es6-promise.auto.min.js b/public/vendor/plugins/es6-promise/es6-promise.auto.min.js deleted file mode 100644 index 77596bdaf8..0000000000 --- a/public/vendor/plugins/es6-promise/es6-promise.auto.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ES6Promise=e()}(this,function(){"use strict";function t(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function e(t){return"function"==typeof t}function n(t){B=t}function r(t){G=t}function o(){return function(){return process.nextTick(a)}}function i(){return"undefined"!=typeof z?function(){z(a)}:c()}function s(){var t=0,e=new J(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;tn;n++)o(e,e._deferreds[n]);e._deferreds=null}function u(e,n){var t=!1;try{e(function(e){t||(t=!0,r(n,e))},function(e){t||(t=!0,i(n,e))})}catch(o){if(t)return;t=!0,i(n,o)}}var c=setTimeout;t.prototype["catch"]=function(e){return this.then(null,e)},t.prototype.then=function(e,t){var r=new this.constructor(n);return o(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,t,r)),r},t.prototype["finally"]=e,t.all=function(e){return new t(function(n,t){function o(e,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(n){o(e,n)},t)}r[e]=f,0==--i&&n(r)}catch(c){t(c)}}if(!e||"undefined"==typeof e.length)throw new TypeError("Promise.all accepts an array");var r=Array.prototype.slice.call(e);if(0===r.length)return n([]);for(var i=r.length,f=0;r.length>f;f++)o(f,r[f])})},t.resolve=function(e){return e&&"object"==typeof e&&e.constructor===t?e:new t(function(n){n(e)})},t.reject=function(e){return new t(function(n,t){t(e)})},t.race=function(e){return new t(function(n,t){for(var o=0,r=e.length;r>o;o++)e[o].then(n,t)})},t._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){c(e,0)},t._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=t}); diff --git a/templates/base/footer.tmpl b/templates/base/footer.tmpl index 98c9871f20..2481b2187c 100644 --- a/templates/base/footer.tmpl +++ b/templates/base/footer.tmpl @@ -122,7 +122,6 @@ {{if .EnableHeatmap}} - {{if .PageIsUserProfile}}