
* Detect wizard cancel/close and interrupt import. This will still have to wait for current fetch (file or metadata) to complete but will then advance to the cleanup stage * Advance progress bar during metadata fetch * Add some extra logging
373 lines
11 KiB
JavaScript
373 lines
11 KiB
JavaScript
import FilePicker from 'zotero/modules/filePicker';
|
|
|
|
var Zotero_Import_Wizard = {
|
|
_wizard: null,
|
|
_dbs: null,
|
|
_file: null,
|
|
_translation: null,
|
|
_mendeleyOnlineRedirectURLWithCode: null,
|
|
_mendeleyCode: null,
|
|
|
|
|
|
init: async function () {
|
|
this._wizard = document.getElementById('import-wizard');
|
|
var dbs = await Zotero_File_Interface.findMendeleyDatabases();
|
|
if (dbs.length) {
|
|
// Local import disabled
|
|
//document.getElementById('radio-import-source-mendeley').hidden = false;
|
|
}
|
|
|
|
// If no existing collections or non-trash items in the library, don't create a new
|
|
// collection by default
|
|
var args = window.arguments[0].wrappedJSObject;
|
|
if (args && args.libraryID) {
|
|
let sql = "SELECT ROWID FROM collections WHERE libraryID=?1 "
|
|
+ "UNION "
|
|
+ "SELECT ROWID FROM items WHERE libraryID=?1 "
|
|
// Not in trash
|
|
+ "AND itemID NOT IN (SELECT itemID FROM deletedItems) "
|
|
// And not a child item (which doesn't necessarily show up in the trash)
|
|
+ "AND itemID NOT IN (SELECT itemID FROM itemNotes WHERE parentItemID IS NOT NULL) "
|
|
+ "AND itemID NOT IN (SELECT itemID FROM itemAttachments WHERE parentItemID IS NOT NULL) "
|
|
+ "LIMIT 1";
|
|
if (!await Zotero.DB.valueQueryAsync(sql, args.libraryID)) {
|
|
document.getElementById('create-collection-checkbox').removeAttribute('checked');
|
|
}
|
|
}
|
|
|
|
if (args && args.mendeleyCode) {
|
|
this._mendeleyCode = args.mendeleyCode;
|
|
this._wizard.goTo('page-options');
|
|
}
|
|
|
|
// Update labels
|
|
document.getElementById('radio-import-source-mendeley-online').label
|
|
= `Mendeley Reference Manager (${Zotero.getString('import.onlineImport')})`;
|
|
document.getElementById('radio-import-source-mendeley').label
|
|
= `Mendeley Desktop (${Zotero.getString('import.localImport')})`;
|
|
document.getElementById('file-handling-store').label = Zotero.getString(
|
|
'import.fileHandling.store',
|
|
Zotero.appName
|
|
);
|
|
document.getElementById('file-handling-link').label = Zotero.getString('import.fileHandling.link');
|
|
document.getElementById('file-handling-description').textContent = Zotero.getString(
|
|
'import.fileHandling.description',
|
|
Zotero.appName
|
|
);
|
|
|
|
Zotero.Translators.init(); // async
|
|
},
|
|
|
|
onCancel: function () {
|
|
if (this._translation && this._translation.interrupt) {
|
|
this._translation.interrupt();
|
|
}
|
|
},
|
|
|
|
onModeChosen: async function () {
|
|
var wizard = this._wizard;
|
|
|
|
var mode = document.getElementById('import-source').selectedItem.id;
|
|
try {
|
|
switch (mode) {
|
|
case 'radio-import-source-file':
|
|
await this.chooseFile();
|
|
break;
|
|
|
|
case 'radio-import-source-mendeley-online':
|
|
wizard.goTo('mendeley-online-explanation');
|
|
wizard.canRewind = true;
|
|
break;
|
|
|
|
case 'radio-import-source-mendeley':
|
|
this._dbs = await Zotero_File_Interface.findMendeleyDatabases();
|
|
// This shouldn't happen, because we only show the wizard if there are databases
|
|
if (!this._dbs.length) {
|
|
throw new Error("No databases found");
|
|
}
|
|
this._populateFileList(this._dbs);
|
|
document.getElementById('file-options-header').textContent
|
|
= Zotero.getString('fileInterface.chooseAppDatabaseToImport', 'Mendeley')
|
|
wizard.goTo('page-file-list');
|
|
wizard.canRewind = true;
|
|
this._enableCancel();
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unknown mode ${mode}`);
|
|
}
|
|
}
|
|
catch (e) {
|
|
this._onDone(
|
|
Zotero.getString('general.error'),
|
|
Zotero.getString('fileInterface.importError'),
|
|
true
|
|
);
|
|
throw e;
|
|
}
|
|
},
|
|
|
|
onMendeleyOnlineShow: async function () {
|
|
document.getElementById('mendeley-online-description').textContent = Zotero.getString(
|
|
'import.online.intro', [Zotero.appName, 'Mendeley Reference Manager', 'Mendeley']
|
|
);
|
|
document.getElementById('mendeley-online-description2').textContent = Zotero.getString(
|
|
'import.online.intro2', [Zotero.appName, 'Mendeley']
|
|
);
|
|
},
|
|
|
|
onMendeleyOnlineAdvance: function () {
|
|
if (!this._mendeleyOnlineRedirectURLWithCode) {
|
|
Zotero_File_Interface.authenticateMendeleyOnline();
|
|
window.close();
|
|
}
|
|
},
|
|
|
|
goToStart: function () {
|
|
this._wizard.goTo('page-start');
|
|
this._wizard.canAdvance = true;
|
|
return false;
|
|
},
|
|
|
|
|
|
chooseFile: async function (translation) {
|
|
var translation = new Zotero.Translate.Import();
|
|
var translators = await translation.getTranslators();
|
|
var fp = new FilePicker();
|
|
fp.init(window, Zotero.getString("fileInterface.import"), fp.modeOpen);
|
|
|
|
fp.appendFilters(fp.filterAll);
|
|
|
|
var collation = Zotero.getLocaleCollation();
|
|
|
|
// Add Mendeley DB, which isn't a translator
|
|
var mendeleyFilter = {
|
|
label: "Mendeley Database", // TODO: Localize
|
|
target: "*.sqlite"
|
|
};
|
|
var filters = [...translators];
|
|
filters.push(mendeleyFilter);
|
|
|
|
filters.sort((a, b) => collation.compareString(1, a.label, b.label));
|
|
for (let filter of filters) {
|
|
fp.appendFilter(filter.label, "*." + filter.target);
|
|
}
|
|
|
|
var rv = await fp.show();
|
|
if (rv !== fp.returnOK && rv !== fp.returnReplace) {
|
|
return false;
|
|
}
|
|
|
|
Zotero.debug(`File is ${fp.file}`);
|
|
|
|
this._file = fp.file;
|
|
this._wizard.canAdvance = true;
|
|
this._wizard.goTo('page-options');
|
|
},
|
|
|
|
|
|
/**
|
|
* When a file is clicked on in the file list
|
|
*/
|
|
onFileSelected: async function () {
|
|
var index = document.getElementById('file-list').selectedIndex;
|
|
if (index != -1) {
|
|
this._file = this._dbs[index].path;
|
|
this._wizard.canAdvance = true;
|
|
}
|
|
else {
|
|
this._file = null;
|
|
this._wizard.canAdvance = false;
|
|
}
|
|
},
|
|
|
|
|
|
/**
|
|
* When the user clicks "Other…" to choose a file not in the list
|
|
*/
|
|
chooseMendeleyDB: async function () {
|
|
document.getElementById('file-list').selectedIndex = -1;
|
|
var fp = new FilePicker();
|
|
fp.init(window, Zotero.getString('fileInterface.import'), fp.modeOpen);
|
|
fp.appendFilter("Mendeley Database", "*.sqlite"); // TODO: Localize
|
|
var rv = await fp.show();
|
|
if (rv != fp.returnOK) {
|
|
return false;
|
|
}
|
|
this._file = fp.file;
|
|
this._wizard.canAdvance = true;
|
|
this._wizard.advance();
|
|
},
|
|
|
|
|
|
onOptionsShown: function () {
|
|
document.getElementById('file-handling-options').hidden = !!this._mendeleyCode;
|
|
},
|
|
|
|
|
|
onBeforeImport: async function (translation) {
|
|
// Unrecognized translator
|
|
if (!translation) {
|
|
// Allow error dialog to be displayed, and then close window
|
|
setTimeout(function () {
|
|
window.close();
|
|
});
|
|
return;
|
|
}
|
|
|
|
this._translation = translation;
|
|
|
|
// Switch to progress pane
|
|
this._wizard.goTo('page-progress');
|
|
var pm = document.getElementById('import-progressmeter');
|
|
|
|
translation.setHandler('itemDone', function () {
|
|
pm.value = translation.getProgress();
|
|
});
|
|
},
|
|
|
|
|
|
onImportStart: async function () {
|
|
if (!this._file && !this._mendeleyCode) {
|
|
let index = document.getElementById('file-list').selectedIndex;
|
|
this._file = this._dbs[index].path;
|
|
}
|
|
this._disableCancel();
|
|
this._wizard.canRewind = false;
|
|
this._wizard.canAdvance = false;
|
|
|
|
try {
|
|
let result = await Zotero_File_Interface.importFile({
|
|
file: this._file,
|
|
onBeforeImport: this.onBeforeImport.bind(this),
|
|
addToLibraryRoot: !document.getElementById('create-collection-checkbox')
|
|
.hasAttribute('checked'),
|
|
linkFiles: document.getElementById('file-handling-radio').selectedIndex == 1,
|
|
mendeleyCode: this._mendeleyCode
|
|
});
|
|
|
|
// Cancelled by user or due to error
|
|
if (!result) {
|
|
window.close();
|
|
return;
|
|
}
|
|
|
|
let numItems = this._translation.newItems.length;
|
|
this._onDone(
|
|
Zotero.getString('fileInterface.importComplete'),
|
|
Zotero.getString(`fileInterface.itemsWereImported`, numItems, numItems)
|
|
);
|
|
}
|
|
catch (e) {
|
|
if (e.message == 'Encrypted Mendeley database') {
|
|
let url = 'https://www.zotero.org/support/kb/mendeley_import';
|
|
let HTML_NS = 'http://www.w3.org/1999/xhtml'
|
|
let elem = document.createElementNS(HTML_NS, 'div');
|
|
elem.innerHTML = `The selected Mendeley database cannot be read, likely because it `
|
|
+ `is encrypted. See <a href="${url}" class="text-link">How do I import a `
|
|
+ `Mendeley library into Zotero?</a> for more information.`
|
|
this._onDone(Zotero.getString('general.error'), elem);
|
|
}
|
|
else {
|
|
this._onDone(
|
|
Zotero.getString('general.error'),
|
|
Zotero_File_Interface.makeImportErrorString(this._translation),
|
|
true
|
|
);
|
|
}
|
|
throw e;
|
|
}
|
|
},
|
|
|
|
|
|
reportError: function () {
|
|
Zotero.getActiveZoteroPane().reportErrors();
|
|
window.close();
|
|
},
|
|
|
|
|
|
_populateFileList: async function (files) {
|
|
var listbox = document.getElementById('file-list');
|
|
|
|
// Remove existing entries
|
|
var items = listbox.getElementsByTagName('listitem');
|
|
for (let item of items) {
|
|
listbox.removeChild(item);
|
|
}
|
|
|
|
for (let file of files) {
|
|
let li = document.createElement('listitem');
|
|
|
|
let name = document.createElement('listcell');
|
|
// Simply filenames
|
|
let nameStr = file.name
|
|
.replace(/\.sqlite$/, '')
|
|
.replace(/@www\.mendeley\.com$/, '');
|
|
if (nameStr == 'online') {
|
|
nameStr = Zotero.getString('dataDir.default', 'online.sqlite');
|
|
}
|
|
name.setAttribute('label', nameStr + ' ');
|
|
li.appendChild(name);
|
|
|
|
let lastModified = document.createElement('listcell');
|
|
lastModified.setAttribute('label', file.lastModified.toLocaleString() + ' ');
|
|
li.appendChild(lastModified);
|
|
|
|
let size = document.createElement('listcell');
|
|
size.setAttribute(
|
|
'label',
|
|
Zotero.getString('general.nMegabytes', (file.size / 1024 / 1024).toFixed(1)) + ' '
|
|
);
|
|
li.appendChild(size);
|
|
|
|
listbox.appendChild(li);
|
|
}
|
|
|
|
if (files.length == 1) {
|
|
listbox.selectedIndex = 0;
|
|
}
|
|
},
|
|
|
|
|
|
_enableCancel: function () {
|
|
this._wizard.getButton('cancel').disabled = false;
|
|
},
|
|
|
|
|
|
_disableCancel: function () {
|
|
this._wizard.getButton('cancel').disabled = true;
|
|
},
|
|
|
|
|
|
_onDone: function (label, description, showReportErrorButton) {
|
|
var wizard = this._wizard;
|
|
wizard.getPageById('page-done').setAttribute('label', label);
|
|
|
|
var xulElem = document.getElementById('result-description');
|
|
var htmlElem = document.getElementById('result-description-html');
|
|
|
|
if (description instanceof HTMLElement) {
|
|
htmlElem.appendChild(description);
|
|
Zotero.Utilities.Internal.updateHTMLInXUL(htmlElem, { callback: () => window.close() });
|
|
xulElem.hidden = true;
|
|
htmlElem.setAttribute('display', 'block');
|
|
}
|
|
else {
|
|
xulElem.textContent = description;
|
|
xulElem.hidden = false;
|
|
htmlElem.setAttribute('display', 'none');
|
|
}
|
|
document.getElementById('result-description');
|
|
|
|
if (showReportErrorButton) {
|
|
let button = document.getElementById('result-report-error');
|
|
button.setAttribute('label', Zotero.getString('errorReport.reportError'));
|
|
button.hidden = false;
|
|
}
|
|
|
|
// When done, move to last page and allow closing
|
|
wizard.canAdvance = true;
|
|
wizard.goTo('page-done');
|
|
wizard.canRewind = false;
|
|
}
|
|
};
|