From 91c385a67a234e8d32df3347e88145c76972116a Mon Sep 17 00:00:00 2001 From: Tom Najdek Date: Thu, 15 Dec 2022 19:35:29 +0100 Subject: [PATCH] Add option to Mendeley importer to relink items New option only appears if importer version is < 1 or not present. It will: * Skip fetching collections and attachments * Skip any new items * Update relations on existing items --- chrome/content/zotero/fileInterface.js | 1 + chrome/content/zotero/import/importWizard.js | 22 ++++++-- chrome/content/zotero/import/importWizard.xul | 5 ++ .../zotero/import/mendeley/mendeleyImport.js | 30 +++++++---- chrome/locale/en-US/zotero/zotero.dtd | 1 + chrome/skin/default/zotero/importWizard.css | 4 ++ test/tests/mendeleyImportTest.js | 51 +++++++++++++++++++ 7 files changed, 101 insertions(+), 13 deletions(-) diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js index 59eedb6d91..c5d2b583e3 100644 --- a/chrome/content/zotero/fileInterface.js +++ b/chrome/content/zotero/fileInterface.js @@ -450,6 +450,7 @@ var Zotero_File_Interface = new function() { translation.mendeleyAuth = options.mendeleyAuth; translation.mendeleyCode = options.mendeleyCode; translation.newItemsOnly = options.newItemsOnly; + translation.relinkOnly = options.relinkOnly; } else { // Check if the file is an SQLite database diff --git a/chrome/content/zotero/import/importWizard.js b/chrome/content/zotero/import/importWizard.js index 87da262dbc..52e8640a7e 100644 --- a/chrome/content/zotero/import/importWizard.js +++ b/chrome/content/zotero/import/importWizard.js @@ -12,6 +12,7 @@ var Zotero_Import_Wizard = { _mendeleyCode: null, _mendeleyAuth: null, _mendeleyHasPreviouslyImported: false, + _mendeleyImporterVersion: 0, _isZotfileInstalled: false, init: async function () { @@ -31,6 +32,8 @@ var Zotero_Import_Wizard = { const relSQL = 'SELECT ROWID FROM itemRelations WHERE predicateID = ? LIMIT 1'; this._mendeleyHasPreviouslyImported = !!(await Zotero.DB.valueQueryAsync(relSQL, predicateID)); } + + this._mendeleyImporterVersion = parseInt((await Zotero.DB.valueQueryAsync("SELECT value FROM settings WHERE setting='mendeleyImport' AND key='version'")) || 0); // If no existing collections or non-trash items in the library, don't create a new // collection by default @@ -82,6 +85,8 @@ var Zotero_Import_Wizard = { document.getElementById('mendeley-username').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this)); document.getElementById('mendeley-password').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this)); + document.getElementById('relink-only-checkbox').addEventListener('command', this.onRelinkOnlyChange.bind(this)); + Zotero.Translators.init(); // async }, @@ -186,6 +191,16 @@ var Zotero_Import_Wizard = { this._wizard.canAdvance = document.getElementById('mendeley-username').value.length > 0 && document.getElementById('mendeley-password').value.length > 0; }, + + onRelinkOnlyChange: function () { + if (document.getElementById('relink-only-checkbox').checked) { + document.getElementById('new-items-only-checkbox').checked = true; + document.getElementById('create-collection-checkbox').checked = false; + } + + document.getElementById('new-items-only-checkbox').disabled = document.getElementById('relink-only-checkbox').checked; + document.getElementById('create-collection-checkbox').disabled = document.getElementById('relink-only-checkbox').checked; + }, goToStart: function () { this._wizard.goTo('page-start'); @@ -268,6 +283,7 @@ var Zotero_Import_Wizard = { document.getElementById('file-handling-options').hidden = !!(this._mendeleyAuth || this._mendeleyCode); const hideExtraMendeleyOptions = !this._mendeleyHasPreviouslyImported || !(this._mendeleyAuth || this._mendeleyCode); document.getElementById('mendeley-options').hidden = hideExtraMendeleyOptions; + document.getElementById('relink-only-wrapper').hidden = hideExtraMendeleyOptions || this._mendeleyImporterVersion > 0; if (hideExtraMendeleyOptions) { document.getElementById('new-items-only-checkbox').removeAttribute('checked'); } @@ -309,12 +325,12 @@ var Zotero_Import_Wizard = { let result = await Zotero_File_Interface.importFile({ file: this._file, onBeforeImport: this.onBeforeImport.bind(this), - addToLibraryRoot: !document.getElementById('create-collection-checkbox') - .hasAttribute('checked'), + addToLibraryRoot: !document.getElementById('create-collection-checkbox').checked, linkFiles: document.getElementById('file-handling-radio').selectedIndex == 1, mendeleyAuth: this._mendeleyAuth, mendeleyCode: this._mendeleyCode, - newItemsOnly: document.getElementById('new-items-only-checkbox').hasAttribute('checked') + newItemsOnly: document.getElementById('new-items-only-checkbox').checked, + relinkOnly: document.getElementById('relink-only-checkbox').checked }); // Cancelled by user or due to error diff --git a/chrome/content/zotero/import/importWizard.xul b/chrome/content/zotero/import/importWizard.xul index 17788ecb19..7036de14a1 100644 --- a/chrome/content/zotero/import/importWizard.xul +++ b/chrome/content/zotero/import/importWizard.xul @@ -78,6 +78,11 @@ onpageshow="Zotero_Import_Wizard.onOptionsShown()" onpagerewound="return Zotero_Import_Wizard.goToStart()" onpageadvanced="Zotero_Import_Wizard.onImportStart()"> + + + + + diff --git a/chrome/content/zotero/import/mendeley/mendeleyImport.js b/chrome/content/zotero/import/mendeley/mendeleyImport.js index 532416289c..4703808de2 100644 --- a/chrome/content/zotero/import/mendeley/mendeleyImport.js +++ b/chrome/content/zotero/import/mendeley/mendeleyImport.js @@ -32,6 +32,7 @@ var Zotero_Import_Mendeley = function () { this.newCollections = []; this.mendeleyAuth = null; this.newItemsOnly = false; + this.relinkOnly = false; this._tokens = null; this._db = null; @@ -92,13 +93,15 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) { skipSelect: true, ...(options.saveOptions || {}) }; + + this.newItemsOnly = this.newItemsOnly || this.relinkOnly; const libraryID = options.libraryID || Zotero.Libraries.userLibraryID; const { key: rootCollectionKey } = options.collections ? Zotero.Collections.getLibraryAndKeyFromID(options.collections[0]) : {}; - Zotero.debug(`Begining Mendeley import at ${this._started}. libraryID: ${libraryID}, linkFiles: ${this.linkFiles}, rootCollectionKey: ${rootCollectionKey}`); + Zotero.debug(`Begining Mendeley import at ${this._started}. libraryID: ${libraryID}, linkFiles: ${this.linkFiles}, rootCollectionKey: ${rootCollectionKey}, newItemsOnly: ${this.newItemsOnly}, relinkOnly: ${this.relinkOnly}`); // TODO: Get appropriate version based on schema version const mapVersion = 83; @@ -135,14 +138,17 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) { this._progressMax = 50; this._itemDone(); - const folders = this._tokens - ? await this._getFoldersAPI(mendeleyGroupID) - : await this._getFoldersDB(mendeleyGroupID); + let folderKeys = new Map(); + if(!this.relinkOnly) { + const folders = this._tokens + ? await this._getFoldersAPI(mendeleyGroupID) + : await this._getFoldersDB(mendeleyGroupID); - const collectionJSON = this._foldersToAPIJSON(folders, rootCollectionKey); - const folderKeys = this._getFolderKeys(collectionJSON); + const collectionJSON = this._foldersToAPIJSON(folders, rootCollectionKey); + folderKeys = this._getFolderKeys(collectionJSON); - await this._saveCollections(libraryID, collectionJSON, folderKeys); + await this._saveCollections(libraryID, collectionJSON, folderKeys); + } this._interruptChecker(true); // @@ -175,13 +181,13 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) { this._interruptChecker(true); - let collections = this._tokens + let collections = this.relinkOnly ? new Map() : this._tokens ? await this._getDocumentCollectionsAPI(documents, rootCollectionKey, folderKeys) : await this._getDocumentCollectionsDB(mendeleyGroupID, documents, rootCollectionKey, folderKeys); this._interruptChecker(true); - - let files = this._tokens + + let files = this.relinkOnly ? new Map() : this._tokens ? await this._getDocumentFilesAPI(documents) : await this._getDocumentFilesDB(mendeleyGroupID); @@ -1330,6 +1336,10 @@ Zotero_Import_Mendeley.prototype._saveItems = async function (libraryID, json) { await item.loadPrimaryData(); } } + + if(this.relinkOnly && !isMappedToExisting) { + continue; + } // Remove external id before save let toSave = Object.assign({}, itemJSON); diff --git a/chrome/locale/en-US/zotero/zotero.dtd b/chrome/locale/en-US/zotero/zotero.dtd index 065ab13062..6ece1b51c4 100644 --- a/chrome/locale/en-US/zotero/zotero.dtd +++ b/chrome/locale/en-US/zotero/zotero.dtd @@ -187,6 +187,7 @@ + diff --git a/chrome/skin/default/zotero/importWizard.css b/chrome/skin/default/zotero/importWizard.css index 99cd5cf261..fd9f229e0b 100644 --- a/chrome/skin/default/zotero/importWizard.css +++ b/chrome/skin/default/zotero/importWizard.css @@ -121,4 +121,8 @@ button, checkbox { margin-top: 1.3em; color: red; font-weight: bold; +} + +[disabled="true"] .checkbox-label { + opacity: .5; } \ No newline at end of file diff --git a/test/tests/mendeleyImportTest.js b/test/tests/mendeleyImportTest.js index d176806ff0..8c257cf9af 100644 --- a/test/tests/mendeleyImportTest.js +++ b/test/tests/mendeleyImportTest.js @@ -402,5 +402,56 @@ describe('Zotero_Import_Mendeley', function () { assert.equal(report.getField('title'), 'Sample Report'); assert.equal(report.getRelations()['mendeleyDB:documentUUID'], '616ec6d1-8d23-4414-8b6e-7bb129677577'); }); + + it("should only correct IDs and not add new items if \"relinkOnly\" is configured", async () => { + setHTTPResponse(server, 'https://api.mendeley.com/', { + method: 'GET', + url: `documents?view=all&limit=500`, + status: 200, + headers: {}, + json: JSON.parse( + await Zotero.File.getContentsFromURLAsync('resource://zotero-unit-tests/data/mendeleyMock/items-simple-no-desktop-id.json') + ) + }); + const importer1 = getImporter(); + await importer1.translate({ + libraryID: Zotero.Libraries.userLibraryID, + collections: null, + linkFiles: false, + }); + + const report = (await Zotero.Relations + .getByPredicateAndObject('item', 'mendeleyDB:remoteDocumentUUID', '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef')) + .filter(item => item.libraryID == Zotero.Libraries.userLibraryID && !item.deleted) + .shift(); + + assert.equal(report.getField('title'), 'Sample Report'); + assert.equal(report.getRelations()['mendeleyDB:documentUUID'], '07a74c26-28d1-4d9f-a60d-3f3bc5ef76ef'); + + setHTTPResponse(server, 'https://api.mendeley.com/', { + method: 'GET', + url: `documents?view=all&limit=500`, + status: 200, + headers: {}, + json: JSON.parse( + await Zotero.File.getContentsFromURLAsync('resource://zotero-unit-tests/data/mendeleyMock/items-updated.json') + ) + }); + + const importer2 = getImporter(); + importer2.relinkOnly = true; + await importer2.translate({ + libraryID: Zotero.Libraries.userLibraryID, + collections: null, + linkFiles: false, + }); + + assert.equal(report.getField('title'), 'Sample Report'); + assert.equal(report.getRelations()['mendeleyDB:documentUUID'], '616ec6d1-8d23-4414-8b6e-7bb129677577'); + + const noNewItemHere = await Zotero.Relations.getByPredicateAndObject('item', 'mendeleyDB:documentUUID', '86e56a00-5ae5-4fe8-a977-9298a03b16d6'); + assert.lengthOf(noNewItemHere, 0); + + }); }); });