From 05ff16c17fa03b47ff418029e78ff910f497abae Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Thu, 1 Jun 2017 15:33:00 -0400 Subject: [PATCH] Fix some breakage from 013dc958b3 --- .../content/zotero/xpcom/sync/syncEngine.js | 42 +---- .../content/zotero/xpcom/sync/syncRunner.js | 157 ++++++++++-------- test/tests/syncRunnerTest.js | 47 ++++++ 3 files changed, 146 insertions(+), 100 deletions(-) diff --git a/chrome/content/zotero/xpcom/sync/syncEngine.js b/chrome/content/zotero/xpcom/sync/syncEngine.js index 08280ce0e8..25d552ff78 100644 --- a/chrome/content/zotero/xpcom/sync/syncEngine.js +++ b/chrome/content/zotero/xpcom/sync/syncEngine.js @@ -1137,6 +1137,7 @@ Zotero.Sync.Data.Engine.prototype._uploadObjects = Zotero.Promise.coroutine(func // Handle failed objects for (let index in results.failed) { let { code, message, data } = results.failed[index]; + let key = jsonBatch[index].key; // API errors are HTML message = Zotero.Utilities.unescapeHTML(message); let e = new Error(message); @@ -1145,12 +1146,13 @@ Zotero.Sync.Data.Engine.prototype._uploadObjects = Zotero.Promise.coroutine(func if (data) { e.data = data; } - Zotero.logError(`Error ${code} for ${objectType} ${jsonBatch[index].key} in ` + e.objectType = objectType; + e.object = objectsClass.getByLibraryAndKey(this.libraryID, key); + + Zotero.logError(`Error ${code} for ${objectType} ${key} in ` + this.library.name + ":\n\n" + e); - let keepGoing = yield this._checkObjectUploadError( - objectType, jsonBatch[index].key, e, queue - ); + let keepGoing = yield this._checkObjectUploadError(objectType, key, e, queue, batch); if (keepGoing) { numSuccessful++; continue; @@ -1604,7 +1606,7 @@ Zotero.Sync.Data.Engine.prototype._handleUploadError = Zotero.Promise.coroutine( }); -Zotero.Sync.Data.Engine.prototype._checkObjectUploadError = Zotero.Promise.coroutine(function* (objectType, key, e) { +Zotero.Sync.Data.Engine.prototype._checkObjectUploadError = Zotero.Promise.coroutine(function* (objectType, key, e, queue, batch) { var { code, data, message } = e; // If an item's dependency is missing remotely and it isn't in the queue (which @@ -1663,35 +1665,7 @@ Zotero.Sync.Data.Engine.prototype._checkObjectUploadError = Zotero.Promise.corou else if (code == 404 || code == 412) { throw e; } - else if (code == 413) { - // Note too long - if (objectType == 'item') { - let item = Zotero.Items.getByLibraryAndKey(this.libraryID, key); - if (item) { - // Throw an error that adds a button for selecting the item to the sync error dialog - if (message.includes(' { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var win = wm.getMostRecentWindow("navigator:browser"); - win.ZoteroPane.selectItem(item.id); - } - } - ); - } - throw e; - } - } + return false; }); diff --git a/chrome/content/zotero/xpcom/sync/syncRunner.js b/chrome/content/zotero/xpcom/sync/syncRunner.js index e3f001aa84..8ad35e8030 100644 --- a/chrome/content/zotero/xpcom/sync/syncRunner.js +++ b/chrome/content/zotero/xpcom/sync/syncRunner.js @@ -981,79 +981,104 @@ Zotero.Sync.Runner_Module = function (options = {}) { } } else if (e.name && e.name == 'ZoteroObjectUploadError') { + let { code, data, objectType, object } = e; + // Tag too long - if (e.code == 413 && e.data && e.data.tag !== undefined) { - // Show long tag fixer and handle result - e.dialogButtonText = Zotero.getString('general.fix'); - e.dialogButtonCallback = Zotero.Promise.coroutine(function* () { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - var lastWin = wm.getMostRecentWindow("navigator:browser"); - - // Open long tag fixer for every long tag in every editable library we're syncing - var editableLibraries = options.libraries - .filter(x => Zotero.Libraries.get(x).editable); - for (let libraryID of editableLibraries) { - let oldTagIDs = yield Zotero.Tags.getLongTagsInLibrary(libraryID); - for (let oldTagID of oldTagIDs) { - let oldTag = Zotero.Tags.getName(oldTagID); - let dataOut = { result: null }; - lastWin.openDialog( - 'chrome://zotero/content/longTagFixer.xul', - '', - 'chrome,modal,centerscreen', - oldTag, - dataOut - ); - // If dialog was cancelled, stop - if (!dataOut.result) { - return; - } - switch (dataOut.result.op) { - case 'split': - for (let libraryID of editableLibraries) { - let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID); - yield Zotero.DB.executeTransaction(function* () { - for (let itemID of itemIDs) { - let item = yield Zotero.Items.getAsync(itemID); - for (let tag of dataOut.result.tags) { - item.addTag(tag); + if (code == 413 && objectType == 'item') { + if (data && data.tag !== undefined) { + // Show long tag fixer and handle result + e.dialogButtonText = Zotero.getString('general.fix'); + e.dialogButtonCallback = Zotero.Promise.coroutine(function* () { + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var lastWin = wm.getMostRecentWindow("navigator:browser"); + + // Open long tag fixer for every long tag in every editable library we're syncing + var editableLibraries = options.libraries + .filter(x => Zotero.Libraries.get(x).editable); + for (let libraryID of editableLibraries) { + let oldTagIDs = yield Zotero.Tags.getLongTagsInLibrary(libraryID); + for (let oldTagID of oldTagIDs) { + let oldTag = Zotero.Tags.getName(oldTagID); + let dataOut = { result: null }; + lastWin.openDialog( + 'chrome://zotero/content/longTagFixer.xul', + '', + 'chrome,modal,centerscreen', + oldTag, + dataOut + ); + // If dialog was cancelled, stop + if (!dataOut.result) { + return; + } + switch (dataOut.result.op) { + case 'split': + for (let libraryID of editableLibraries) { + let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID); + yield Zotero.DB.executeTransaction(function* () { + for (let itemID of itemIDs) { + let item = yield Zotero.Items.getAsync(itemID); + for (let tag of dataOut.result.tags) { + item.addTag(tag); + } + item.removeTag(oldTag); + yield item.save(); } - item.removeTag(oldTag); - yield item.save(); - } - yield Zotero.Tags.purge(oldTagID); - }); + yield Zotero.Tags.purge(oldTagID); + }); + } + break; + + case 'edit': + for (let libraryID of editableLibraries) { + let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID); + yield Zotero.DB.executeTransaction(function* () { + for (let itemID of itemIDs) { + let item = yield Zotero.Items.getAsync(itemID); + item.replaceTag(oldTag, dataOut.result.tag); + yield item.save(); + } + }); + } + break; + + case 'delete': + for (let libraryID of editableLibraries) { + yield Zotero.Tags.removeFromLibrary(libraryID, oldTagID); + } + break; } - break; - - case 'edit': - for (let libraryID of editableLibraries) { - let itemIDs = yield Zotero.Tags.getTagItems(libraryID, oldTagID); - yield Zotero.DB.executeTransaction(function* () { - for (let itemID of itemIDs) { - let item = yield Zotero.Items.getAsync(itemID); - item.replaceTag(oldTag, dataOut.result.tag); - yield item.save(); - } - }); - } - break; - - case 'delete': - for (let libraryID of editableLibraries) { - yield Zotero.Tags.removeFromLibrary(libraryID, oldTagID); - } - break; } } + + options.restartSync = true; + }); + } + // Note too long + else if (object.isNote()) { + // Throw an error that adds a button for selecting the item to the sync error dialog + if (e.message.includes(' { + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("navigator:browser"); + win.ZoteroPane.selectItem(object.id); + }; + } + + // If not a background sync, show dialog immediately + if (!options.background && e.dialogButtonCallback) { + let maybePromise = e.dialogButtonCallback(); + if (maybePromise && maybePromise.then) { + yield maybePromise; + } } } } diff --git a/test/tests/syncRunnerTest.js b/test/tests/syncRunnerTest.js index b161cac43e..4d4b002e5f 100644 --- a/test/tests/syncRunnerTest.js +++ b/test/tests/syncRunnerTest.js @@ -1033,6 +1033,53 @@ describe("Zotero.Sync.Runner", function () { }); + it("should show a button in error panel to select a too-long note", function* () { + win = yield loadZoteroPane(); + var doc = win.document; + + var text = "".padStart(256, "a"); + var item = yield createDataObject('item', { itemType: 'note', note: text }); + + setResponse('keyInfo.fullAccess'); + setResponse('userGroups.groupVersions'); + setResponse('groups.ownerGroup'); + setResponse('groups.memberGroup'); + + server.respond(function (req) { + if (req.method == "POST" && req.url == baseURL + "users/1/items") { + req.respond( + 200, + { + "Last-Modified-Version": 5 + }, + JSON.stringify({ + successful: {}, + success: {}, + unchanged: {}, + failed: { + "0": { + code: 413, + message: `Note ${Zotero.Utilities.ellipsize(text, 100)} too long` + } + } + }) + ); + } + }); + + yield runner.sync({ libraries: [Zotero.Libraries.userLibraryID] }); + + var errorIcon = doc.getElementById('zotero-tb-sync-error'); + assert.isFalse(errorIcon.hidden); + errorIcon.click(); + var panel = win.document.getElementById('zotero-sync-error-panel'); + assert.include(panel.innerHTML, text.substr(0, 10)); + var buttons = panel.getElementsByTagName('button'); + assert.lengthOf(buttons, 1); + assert.include(buttons[0].label, Zotero.getString('pane.items.showItemInLibrary')); + }); + + // TODO: Test multiple long tags and tags across libraries describe("Long Tag Fixer", function () { it("should split a tag", function* () {