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
This commit is contained in:
parent
80bdf51ecb
commit
197d8d1f3b
7 changed files with 99 additions and 11 deletions
|
@ -450,6 +450,7 @@ var Zotero_File_Interface = new function() {
|
||||||
translation.mendeleyAuth = options.mendeleyAuth;
|
translation.mendeleyAuth = options.mendeleyAuth;
|
||||||
translation.mendeleyCode = options.mendeleyCode;
|
translation.mendeleyCode = options.mendeleyCode;
|
||||||
translation.newItemsOnly = options.newItemsOnly;
|
translation.newItemsOnly = options.newItemsOnly;
|
||||||
|
translation.relinkOnly = options.relinkOnly;
|
||||||
}
|
}
|
||||||
else if (options.folder) {
|
else if (options.folder) {
|
||||||
Components.utils.import("chrome://zotero/content/import/folderImport.js");
|
Components.utils.import("chrome://zotero/content/import/folderImport.js");
|
||||||
|
|
|
@ -43,6 +43,7 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
mendeleyAuth: null,
|
mendeleyAuth: null,
|
||||||
mendeleyCode: null,
|
mendeleyCode: null,
|
||||||
mendeleyHasPreviouslyImported: false,
|
mendeleyHasPreviouslyImported: false,
|
||||||
|
mendeleyImporterVersion: 0,
|
||||||
translation: null,
|
translation: null,
|
||||||
wizard: null,
|
wizard: null,
|
||||||
|
|
||||||
|
@ -72,6 +73,7 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
|
|
||||||
const extensions = await Zotero.getInstalledExtensions();
|
const extensions = await Zotero.getInstalledExtensions();
|
||||||
this.isZotfileInstalled = !!extensions.find(extName => extName.match(/^ZotFile((?!disabled).)*$/));
|
this.isZotfileInstalled = !!extensions.find(extName => extName.match(/^ZotFile((?!disabled).)*$/));
|
||||||
|
this.mendeleyImporterVersion = parseInt((await Zotero.DB.valueQueryAsync("SELECT value FROM settings WHERE setting='mendeleyImport' AND key='version'")) || 0);
|
||||||
|
|
||||||
this.wizard = document.getElementById('import-wizard');
|
this.wizard = document.getElementById('import-wizard');
|
||||||
this.wizard.getPageById('page-start')
|
this.wizard.getPageById('page-start')
|
||||||
|
@ -110,6 +112,8 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
.getElementById('mendeley-username').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this));
|
.getElementById('mendeley-username').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this));
|
||||||
document
|
document
|
||||||
.getElementById('mendeley-password').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this));
|
.getElementById('mendeley-password').addEventListener('keyup', this.onMendeleyAuthKeyUp.bind(this));
|
||||||
|
document
|
||||||
|
.getElementById('relink-only-checkbox').addEventListener('command', this.onRelinkOnlyChange.bind(this));
|
||||||
|
|
||||||
this.wizard.addEventListener('pageshow', this.updateFocus.bind(this));
|
this.wizard.addEventListener('pageshow', this.updateFocus.bind(this));
|
||||||
this.wizard.addEventListener('wizardcancel', this.onCancel.bind(this));
|
this.wizard.addEventListener('wizardcancel', this.onCancel.bind(this));
|
||||||
|
@ -301,6 +305,7 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
document.getElementById('page-options-file-handling').style.display = (this.mendeleyCode || this.mendeleyAuth) ? 'none' : 'block';
|
document.getElementById('page-options-file-handling').style.display = (this.mendeleyCode || this.mendeleyAuth) ? 'none' : 'block';
|
||||||
const hideExtraMendeleyOptions = !this.mendeleyHasPreviouslyImported || !(this.mendeleyAuth || this.mendeleyCode);
|
const hideExtraMendeleyOptions = !this.mendeleyHasPreviouslyImported || !(this.mendeleyAuth || this.mendeleyCode);
|
||||||
document.getElementById('page-options-mendeley').style.display = hideExtraMendeleyOptions ? 'none' : 'block';
|
document.getElementById('page-options-mendeley').style.display = hideExtraMendeleyOptions ? 'none' : 'block';
|
||||||
|
document.getElementById('page-options-relink-only').style.display = (hideExtraMendeleyOptions || this.mendeleyImporterVersion > 0) ? 'none' : null;
|
||||||
if (hideExtraMendeleyOptions) {
|
if (hideExtraMendeleyOptions) {
|
||||||
document.getElementById('new-items-only-checkbox').checked = false;
|
document.getElementById('new-items-only-checkbox').checked = false;
|
||||||
}
|
}
|
||||||
|
@ -354,6 +359,16 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onRelinkOnlyChange() {
|
||||||
|
if (document.getElementById('relink-only-checkbox').checked) {
|
||||||
|
document.getElementById('new-items-only-checkbox').checked = true;
|
||||||
|
document.getElementById('create-collection').checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('new-items-only-checkbox').disabled = document.getElementById('relink-only-checkbox').checked;
|
||||||
|
document.getElementById('create-collection').disabled = document.getElementById('relink-only-checkbox').checked;
|
||||||
|
},
|
||||||
|
|
||||||
onURLInteract(ev) {
|
onURLInteract(ev) {
|
||||||
if (ev.type === 'click' || (ev.type === 'keydown' && ev.key === ' ')) {
|
if (ev.type === 'click' || (ev.type === 'keydown' && ev.key === ' ')) {
|
||||||
Zotero.launchURL(ev.currentTarget.getAttribute('href'));
|
Zotero.launchURL(ev.currentTarget.getAttribute('href'));
|
||||||
|
@ -393,6 +408,7 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
? document.getElementById('other-files').value
|
? document.getElementById('other-files').value
|
||||||
: null;
|
: null;
|
||||||
const newItemsOnly = document.getElementById('new-items-only-checkbox').checked;
|
const newItemsOnly = document.getElementById('new-items-only-checkbox').checked;
|
||||||
|
const relinkOnly = document.getElementById('relink-only-checkbox').checked;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await Zotero_File_Interface.importFile({
|
const result = await Zotero_File_Interface.importFile({
|
||||||
|
@ -406,7 +422,8 @@ const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||||
mimeTypes,
|
mimeTypes,
|
||||||
newItemsOnly,
|
newItemsOnly,
|
||||||
onBeforeImport: this.onBeforeImport.bind(this),
|
onBeforeImport: this.onBeforeImport.bind(this),
|
||||||
recreateStructure
|
recreateStructure,
|
||||||
|
relinkOnly
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cancelled by user or due to error
|
// Cancelled by user or due to error
|
||||||
|
|
|
@ -54,6 +54,9 @@
|
||||||
pageid="page-options"
|
pageid="page-options"
|
||||||
data-header-label-id="import-options"
|
data-header-label-id="import-options"
|
||||||
>
|
>
|
||||||
|
<div class="options-group" id="page-options-relink-only">
|
||||||
|
<checkbox id="relink-only-checkbox" data-l10n-id="import-online-relink-only" />
|
||||||
|
</div>
|
||||||
<div class="options-group" id="page-options-common">
|
<div class="options-group" id="page-options-common">
|
||||||
<checkbox native="true" id="create-collection" data-l10n-id="import-create-collection" />
|
<checkbox native="true" id="create-collection" data-l10n-id="import-create-collection" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,6 +32,7 @@ var Zotero_Import_Mendeley = function () {
|
||||||
this.newCollections = [];
|
this.newCollections = [];
|
||||||
this.mendeleyAuth = null;
|
this.mendeleyAuth = null;
|
||||||
this.newItemsOnly = false;
|
this.newItemsOnly = false;
|
||||||
|
this.relinkOnly = false;
|
||||||
|
|
||||||
this._tokens = null;
|
this._tokens = null;
|
||||||
this._db = null;
|
this._db = null;
|
||||||
|
@ -92,13 +93,15 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) {
|
||||||
skipSelect: true,
|
skipSelect: true,
|
||||||
...(options.saveOptions || {})
|
...(options.saveOptions || {})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.newItemsOnly = this.newItemsOnly || this.relinkOnly;
|
||||||
|
|
||||||
const libraryID = options.libraryID || Zotero.Libraries.userLibraryID;
|
const libraryID = options.libraryID || Zotero.Libraries.userLibraryID;
|
||||||
const { key: rootCollectionKey } = options.collections
|
const { key: rootCollectionKey } = options.collections
|
||||||
? Zotero.Collections.getLibraryAndKeyFromID(options.collections[0])
|
? 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
|
// TODO: Get appropriate version based on schema version
|
||||||
const mapVersion = 83;
|
const mapVersion = 83;
|
||||||
|
@ -135,14 +138,17 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) {
|
||||||
this._progressMax = 50;
|
this._progressMax = 50;
|
||||||
this._itemDone();
|
this._itemDone();
|
||||||
|
|
||||||
const folders = this._tokens
|
let folderKeys = new Map();
|
||||||
? await this._getFoldersAPI(mendeleyGroupID)
|
if(!this.relinkOnly) {
|
||||||
: await this._getFoldersDB(mendeleyGroupID);
|
const folders = this._tokens
|
||||||
|
? await this._getFoldersAPI(mendeleyGroupID)
|
||||||
|
: await this._getFoldersDB(mendeleyGroupID);
|
||||||
|
|
||||||
const collectionJSON = this._foldersToAPIJSON(folders, rootCollectionKey);
|
const collectionJSON = this._foldersToAPIJSON(folders, rootCollectionKey);
|
||||||
const folderKeys = this._getFolderKeys(collectionJSON);
|
folderKeys = this._getFolderKeys(collectionJSON);
|
||||||
|
|
||||||
await this._saveCollections(libraryID, collectionJSON, folderKeys);
|
await this._saveCollections(libraryID, collectionJSON, folderKeys);
|
||||||
|
}
|
||||||
|
|
||||||
this._interruptChecker(true);
|
this._interruptChecker(true);
|
||||||
//
|
//
|
||||||
|
@ -175,13 +181,13 @@ Zotero_Import_Mendeley.prototype.translate = async function (options = {}) {
|
||||||
|
|
||||||
this._interruptChecker(true);
|
this._interruptChecker(true);
|
||||||
|
|
||||||
let collections = this._tokens
|
let collections = this.relinkOnly ? new Map() : this._tokens
|
||||||
? await this._getDocumentCollectionsAPI(documents, rootCollectionKey, folderKeys)
|
? await this._getDocumentCollectionsAPI(documents, rootCollectionKey, folderKeys)
|
||||||
: await this._getDocumentCollectionsDB(mendeleyGroupID, documents, rootCollectionKey, folderKeys);
|
: await this._getDocumentCollectionsDB(mendeleyGroupID, documents, rootCollectionKey, folderKeys);
|
||||||
|
|
||||||
this._interruptChecker(true);
|
this._interruptChecker(true);
|
||||||
|
|
||||||
let files = this._tokens
|
let files = this.relinkOnly ? new Map() : this._tokens
|
||||||
? await this._getDocumentFilesAPI(documents)
|
? await this._getDocumentFilesAPI(documents)
|
||||||
: await this._getDocumentFilesDB(mendeleyGroupID);
|
: await this._getDocumentFilesDB(mendeleyGroupID);
|
||||||
|
|
||||||
|
@ -1330,6 +1336,10 @@ Zotero_Import_Mendeley.prototype._saveItems = async function (libraryID, json) {
|
||||||
await item.loadPrimaryData();
|
await item.loadPrimaryData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.relinkOnly && !isMappedToExisting) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove external id before save
|
// Remove external id before save
|
||||||
let toSave = Object.assign({}, itemJSON);
|
let toSave = Object.assign({}, itemJSON);
|
||||||
|
|
|
@ -61,6 +61,8 @@ import-online-intro2={ -app-name } will never see or store your { $targetApp } p
|
||||||
import-online-form-intro = Please enter your credentials to log in to { $targetAppOnline }. This is necessary to import your { $targetApp } library into { -app-name }.
|
import-online-form-intro = Please enter your credentials to log in to { $targetAppOnline }. This is necessary to import your { $targetApp } library into { -app-name }.
|
||||||
import-online-wrong-credentials = Login to { $targetApp } failed. Please re-enter credentials and try again.
|
import-online-wrong-credentials = Login to { $targetApp } failed. Please re-enter credentials and try again.
|
||||||
import-online-blocked-by-plugin = The import cannot continue with { $plugin } installed. Please disable this plugin and try again.
|
import-online-blocked-by-plugin = The import cannot continue with { $plugin } installed. Please disable this plugin and try again.
|
||||||
|
import-online-relink-only =
|
||||||
|
.label = Relink Mendeley Desktop citations
|
||||||
|
|
||||||
report-error =
|
report-error =
|
||||||
.label = Report Error…
|
.label = Report Error…
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[disabled="true"] .checkbox-label {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
#other-files {
|
#other-files {
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
|
|
@ -402,5 +402,56 @@ describe('Zotero_Import_Mendeley', function () {
|
||||||
assert.equal(report.getField('title'), 'Sample Report');
|
assert.equal(report.getField('title'), 'Sample Report');
|
||||||
assert.equal(report.getRelations()['mendeleyDB:documentUUID'], '616ec6d1-8d23-4414-8b6e-7bb129677577');
|
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);
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue