fx-compat: Convert import wizard to use CE
This commit is contained in:
parent
2820add3d1
commit
5ea43bd65c
14 changed files with 683 additions and 570 deletions
|
@ -389,7 +389,7 @@ var Zotero_File_Interface = new function() {
|
|||
};
|
||||
args.wrappedJSObject = args;
|
||||
|
||||
Services.ww.openWindow(null, "chrome://zotero/content/import/importWizard.xul",
|
||||
Services.ww.openWindow(null, "chrome://zotero/content/import/importWizard.xhtml",
|
||||
"importFile", "chrome,dialog=yes,centerscreen,width=600,height=400,modal", args);
|
||||
};
|
||||
|
||||
|
@ -985,71 +985,6 @@ var Zotero_File_Interface = new function() {
|
|||
}
|
||||
}
|
||||
|
||||
this.authenticateMendeleyOnlinePoll = function (win) {
|
||||
if (win && win[0] && win[0].location) {
|
||||
const matchResult = win[0].location.toString().match(/mendeley_oauth_redirect.html(?:.*?)(?:\?|&)code=(.*?)(?:&|$)/i);
|
||||
if (matchResult) {
|
||||
const mendeleyCode = matchResult[1];
|
||||
Zotero.getMainWindow().setTimeout(() => this.showImportWizard({ mendeleyCode }), 0);
|
||||
|
||||
// Clear all cookies to remove access
|
||||
//
|
||||
// This includes unrelated cookies in the central cookie store, but that's fine for
|
||||
// the moment, since we're not purposely using cookies for anything else.
|
||||
//
|
||||
// TODO: Switch to removeAllSince() once >Fx60
|
||||
try {
|
||||
Cc["@mozilla.org/cookiemanager;1"]
|
||||
.getService(Ci.nsICookieManager)
|
||||
.removeAll();
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
|
||||
win.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (win && !win.closed) {
|
||||
Zotero.getMainWindow().setTimeout(this.authenticateMendeleyOnlinePoll.bind(this, win), 200);
|
||||
}
|
||||
};
|
||||
|
||||
this.authenticateMendeleyOnline = function () {
|
||||
const uri = `https://api.mendeley.com/oauth/authorize?client_id=5907&redirect_uri=https%3A%2F%2Fzotero-static.s3.amazonaws.com%2Fmendeley_oauth_redirect.html&response_type=code&state=&scope=all`;
|
||||
var win = Services.wm.getMostRecentWindow("zotero:basicViewer");
|
||||
if (win) {
|
||||
win.loadURI(uri);
|
||||
}
|
||||
else {
|
||||
const ww = Services.ww;
|
||||
const arg = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
arg.data = uri;
|
||||
win = ww.openWindow(null, "chrome://zotero/content/standalone/basicViewer.xhtml",
|
||||
"basicViewer", "chrome,dialog=yes,resizable,centerscreen,menubar,scrollbars", arg);
|
||||
}
|
||||
|
||||
let browser;
|
||||
let func = function () {
|
||||
win.removeEventListener("load", func);
|
||||
browser = win.document.documentElement.getElementsByTagName('browser')[0];
|
||||
browser.addEventListener("pageshow", innerFunc);
|
||||
};
|
||||
let innerFunc = function () {
|
||||
browser.removeEventListener("pageshow", innerFunc);
|
||||
win.outerWidth = Math.max(640, Math.min(1000, win.screen.availHeight));
|
||||
win.outerHeight = Math.max(480, Math.min(800, win.screen.availWidth));
|
||||
};
|
||||
|
||||
win.addEventListener("load", func);
|
||||
|
||||
// polling executed by the main window because current (wizard) window will be closed
|
||||
Zotero.getMainWindow().setTimeout(this.authenticateMendeleyOnlinePoll.bind(this, win), 200);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an error string reporting a translation failure. Includes the
|
||||
* label of the running translator if available.
|
||||
|
|
|
@ -2,7 +2,22 @@ var EXPORTED_SYMBOLS = ["Zotero_Import_Folder"]; // eslint-disable-line no-unuse
|
|||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js");
|
||||
const multimatch = require('multimatch');
|
||||
|
||||
// matches "*" and "?" wildcards of a glob pattern, case-insensitive
|
||||
function simpleGlobMatch(filename, patterns) {
|
||||
for (const pattern of patterns) {
|
||||
// Convert glob pattern to regex pattern
|
||||
const regexPattern = pattern
|
||||
.replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex characters
|
||||
.replace(/\*/g, '.*') // Replace * with regex equivalent
|
||||
.replace(/\?/g, '.'); // Replace ? with regex equivalent
|
||||
|
||||
if (new RegExp(`^${regexPattern}$`, 'i').test(filename)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const collectFilesRecursive = async (dirPath, parents = [], files = []) => {
|
||||
await Zotero.File.iterateDirectory(dirPath, async ({ isDir, _isSymlink, name, path }) => {
|
||||
|
@ -97,7 +112,7 @@ class Zotero_Import_Folder { // eslint-disable-line camelcase,no-unused-vars
|
|||
async ({ name, path }, index) => {
|
||||
const contentType = mimeTypes[index];
|
||||
this._progress++;
|
||||
if (!(this.types.includes(contentType) || multimatch(name, this.fileTypes, { nocase: true }).length > 0)) {
|
||||
if (!(this.types.includes(contentType) || simpleGlobMatch(name, this.fileTypes))) {
|
||||
// don't bother calculating a hash for file that will be ignored
|
||||
return null;
|
||||
}
|
||||
|
@ -165,12 +180,12 @@ class Zotero_Import_Folder { // eslint-disable-line camelcase,no-unused-vars
|
|||
|
||||
let attachmentItem = null;
|
||||
|
||||
if ((this.types.includes(mimeType) || multimatch(name, this.fileTypes, { nocase: true }).length > 0)) {
|
||||
if ((this.types.includes(mimeType) || simpleGlobMatch(name, this.fileTypes))) {
|
||||
const existingItem = await findItemByHash(libraryID, hash);
|
||||
|
||||
if (existingItem) {
|
||||
existingItem.setCollections([...existingItem.getCollections(), ...parentCollectionIDs]);
|
||||
existingItem.saveTx({ skipSelect: true });
|
||||
await existingItem.saveTx({ skipSelect: true });
|
||||
}
|
||||
else {
|
||||
if (linkFiles) {
|
||||
|
@ -233,9 +248,9 @@ class Zotero_Import_Folder { // eslint-disable-line camelcase,no-unused-vars
|
|||
finally {
|
||||
recognizeQueue.removeListener('rowupdated', processRecognizedItem);
|
||||
}
|
||||
|
||||
await Zotero.Promise.all(
|
||||
itemsToSavePostRecognize.map(async item => item.saveTx({ skipSelect: true }))
|
||||
);
|
||||
|
||||
for (const item of itemsToSavePostRecognize) {
|
||||
await item.saveTx({ skipSelect: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,211 +1,249 @@
|
|||
import FilePicker from 'zotero/modules/filePicker';
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2022 Corporation for Digital Scholarship
|
||||
Vienna, Virginia, USA
|
||||
https://www.zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Zotero is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
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;
|
||||
import FilePicker from 'zotero/filePicker';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ProgressQueueTable from 'components/progressQueueTable';
|
||||
|
||||
/* eslint camelcase: ["error", {allow: ["Zotero_File_Interface", "Zotero_Import_Wizard"]} ] */
|
||||
/* global Zotero_File_Interface: false */
|
||||
|
||||
|
||||
const Zotero_Import_Wizard = { // eslint-disable-line no-unused-vars
|
||||
wizard: null,
|
||||
folder: null,
|
||||
file: null,
|
||||
mendeleyCode: null,
|
||||
libraryID: null,
|
||||
translation: null,
|
||||
|
||||
async getShouldCreateCollection() {
|
||||
const 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";
|
||||
return Zotero.DB.valueQueryAsync(sql, this.libraryID);
|
||||
},
|
||||
|
||||
async init() {
|
||||
const { mendeleyCode, libraryID } = window.arguments[0].wrappedJSObject ?? {};
|
||||
|
||||
this.libraryID = libraryID;
|
||||
this.mendeleyCode = mendeleyCode;
|
||||
|
||||
this.wizard = document.getElementById('import-wizard');
|
||||
this.wizard.getPageById('page-start')
|
||||
.addEventListener('pageadvanced', this.onImportSourceAdvance.bind(this));
|
||||
this.wizard.getPageById('page-mendeley-online-intro')
|
||||
.addEventListener('pagerewound', this.goToStart.bind(this));
|
||||
this.wizard.getPageById('page-mendeley-online-intro')
|
||||
.addEventListener('pageadvanced', this.openMendeleyAuthWindow.bind(this));
|
||||
this.wizard.getPageById('page-options')
|
||||
.addEventListener('pageshow', this.onOptionsPageShow.bind(this));
|
||||
this.wizard.getPageById('page-options')
|
||||
.addEventListener('pageadvanced', this.startImport.bind(this));
|
||||
this.wizard.getPageById('page-progress')
|
||||
.addEventListener('pageshow', this.onProgressPageShow.bind(this));
|
||||
|
||||
document
|
||||
.getElementById('other-files')
|
||||
.addEventListener('keyup', (ev) => {
|
||||
document.getElementById('import-other').checked = ev.currentTarget.value.length > 0;
|
||||
});
|
||||
document
|
||||
.querySelector('#page-done-error-mendeley > a')
|
||||
.addEventListener('click', this.onURLInteract.bind(this));
|
||||
document
|
||||
.querySelector('#page-done-error-mendeley > a')
|
||||
.addEventListener('keydown', this.onURLInteract.bind(this));
|
||||
document
|
||||
.querySelector('#page-done-error > button')
|
||||
.addEventListener('click', this.onReportErrorInteract.bind(this));
|
||||
document
|
||||
.querySelector('#page-done-error > button')
|
||||
.addEventListener('keydown', this.onReportErrorInteract.bind(this));
|
||||
|
||||
this.wizard.addEventListener('pageshow', this.updateFocus.bind(this));
|
||||
this.wizard.addEventListener('wizardcancel', this.onCancel.bind(this));
|
||||
|
||||
const shouldCreateCollection = await this.getShouldCreateCollection();
|
||||
document.getElementById('create-collection').checked = shouldCreateCollection;
|
||||
|
||||
// wizard.shadowRoot content isn't exposed to our css
|
||||
this.wizard.shadowRoot
|
||||
.querySelector('.wizard-header-label').style.fontSize = '16px';
|
||||
|
||||
if (mendeleyCode) {
|
||||
this.wizard.goTo('page-options');
|
||||
}
|
||||
|
||||
// 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');
|
||||
},
|
||||
|
||||
skipToDonePage(label, description, showReportErrorButton = false, isMendeleyError = false) {
|
||||
this.wizard.getPageById('page-done').dataset.headerLabelId = label;
|
||||
|
||||
if (!isMendeleyError) {
|
||||
if (Array.isArray(description)) {
|
||||
document.getElementById('page-done-description').dataset.l10nId = description[0];
|
||||
document.getElementById('page-done-description').dataset.l10nArgs = JSON.stringify(description[1]);
|
||||
}
|
||||
else {
|
||||
document.getElementById('page-done-description').dataset.l10nId = description;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
document.getElementById('page-done-error-mendeley').style.display = isMendeleyError ? 'block' : 'none';
|
||||
document.getElementById('page-done-error').style.display = showReportErrorButton ? 'block' : 'none';
|
||||
|
||||
onCancel: function () {
|
||||
if (this._translation && this._translation.interrupt) {
|
||||
this._translation.interrupt();
|
||||
}
|
||||
},
|
||||
|
||||
onModeChosen: async function () {
|
||||
var wizard = this._wizard;
|
||||
const doneQueueContainer = document.getElementById('done-queue-container');
|
||||
const doneQueue = document.getElementById('done-queue');
|
||||
|
||||
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
|
||||
if (this.folder && !showReportErrorButton) {
|
||||
doneQueueContainer.style.display = 'flex';
|
||||
ReactDOM.render(
|
||||
<ProgressQueueTable progressQueue={ Zotero.ProgressQueues.get('recognize') } />,
|
||||
doneQueue
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
doneQueueContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
this.wizard.goTo('page-done');
|
||||
this.wizard.canRewind = false;
|
||||
},
|
||||
|
||||
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']
|
||||
);
|
||||
goToStart() {
|
||||
this.wizard.goTo('page-start');
|
||||
this.wizard.canAdvance = true;
|
||||
},
|
||||
|
||||
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();
|
||||
async chooseFile() {
|
||||
const translation = new Zotero.Translate.Import();
|
||||
const translators = await translation.getTranslators();
|
||||
const 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 = {
|
||||
const mendeleyFilter = {
|
||||
label: "Mendeley Database", // TODO: Localize
|
||||
target: "*.sqlite"
|
||||
};
|
||||
var filters = [...translators];
|
||||
const 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();
|
||||
|
||||
const rv = await fp.show();
|
||||
if (rv !== fp.returnOK && rv !== fp.returnReplace) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Zotero.debug(`File is ${fp.file}`);
|
||||
|
||||
this._file = fp.file;
|
||||
this._wizard.canAdvance = true;
|
||||
this._wizard.goTo('page-options');
|
||||
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;
|
||||
|
||||
async chooseFolder() {
|
||||
const fp = new FilePicker();
|
||||
fp.init(window, Zotero.getString('attachmentBasePath.selectDir'), fp.modeGetFolder);
|
||||
fp.appendFilters(fp.filterAll);
|
||||
|
||||
const rv = await fp.show();
|
||||
if (rv !== fp.returnOK && rv !== fp.returnReplace) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._file = null;
|
||||
this._wizard.canAdvance = false;
|
||||
|
||||
Zotero.debug(`Folder is ${fp.file}`);
|
||||
|
||||
this.folder = fp.file;
|
||||
this.wizard.canAdvance = true;
|
||||
this.wizard.goTo('page-options');
|
||||
},
|
||||
|
||||
async onImportSourceAdvance(ev) {
|
||||
const selectedMode = document.getElementById('import-source-group').selectedItem.value;
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
try {
|
||||
switch (selectedMode) {
|
||||
case 'file':
|
||||
this.folder = null;
|
||||
await this.chooseFile();
|
||||
break;
|
||||
case 'folder':
|
||||
this.file = null;
|
||||
await this.chooseFolder();
|
||||
break;
|
||||
case 'mendeleyOnline':
|
||||
this.file = null;
|
||||
this.folder = null;
|
||||
this.wizard.goTo('page-mendeley-online-intro');
|
||||
this.wizard.canRewind = true;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown mode ${selectedMode}`);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.skipToDonePage('general-error', 'file-interface-import-error', true);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
onOptionsPageShow() {
|
||||
document.getElementById('page-options-folder-import').style.display = this.folder ? 'block' : 'none';
|
||||
document.getElementById('page-options-file-handling').style.display = this.mendeleyCode ? 'none' : 'block';
|
||||
this.wizard.canRewind = false;
|
||||
},
|
||||
|
||||
|
||||
onOptionsShown: function () {
|
||||
document.getElementById('file-handling-options').hidden = !!this._mendeleyCode;
|
||||
|
||||
openMendeleyAuthWindow(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
const arg = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
arg.data = 'mendeleyImport';
|
||||
|
||||
window.close();
|
||||
|
||||
Services.ww.openWindow(null, "chrome://zotero/content/standalone/basicViewer.xhtml",
|
||||
"basicViewer", "chrome,dialog=yes,centerscreen,width=1000,height=700,modal", arg);
|
||||
},
|
||||
|
||||
|
||||
onBeforeImport: async function (translation) {
|
||||
|
||||
async onBeforeImport(translation) {
|
||||
// Unrecognized translator
|
||||
if (!translation) {
|
||||
// Allow error dialog to be displayed, and then close window
|
||||
|
@ -214,159 +252,112 @@ var Zotero_Import_Wizard = {
|
|||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this._translation = translation;
|
||||
|
||||
|
||||
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();
|
||||
this.wizard.goTo('page-progress');
|
||||
translation.setHandler('itemDone', () => {
|
||||
document.getElementById('import-progress').value = translation.getProgress();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onImportStart: async function () {
|
||||
if (!this._file && !this._mendeleyCode) {
|
||||
let index = document.getElementById('file-list').selectedIndex;
|
||||
this._file = this._dbs[index].path;
|
||||
|
||||
async onProgressPageShow() {
|
||||
this.wizard.canAdvance = false;
|
||||
this.wizard.canRewind = false;
|
||||
const progressQueueContainer = document.getElementById('progress-queue-container');
|
||||
const progressQueue = document.getElementById('progress-queue');
|
||||
if (this.folder) {
|
||||
progressQueueContainer.style.display = 'flex';
|
||||
ReactDOM.render(
|
||||
<ProgressQueueTable progressQueue={Zotero.ProgressQueues.get('recognize')} />,
|
||||
progressQueue
|
||||
);
|
||||
}
|
||||
this._disableCancel();
|
||||
this._wizard.canRewind = false;
|
||||
this._wizard.canAdvance = false;
|
||||
else {
|
||||
progressQueueContainer.style.display = 'none';
|
||||
}
|
||||
},
|
||||
|
||||
onURLInteract(ev) {
|
||||
if (ev.type === 'click' || (ev.type === 'keydown' && ev.key === ' ')) {
|
||||
Zotero.launchURL(ev.currentTarget.getAttribute('href'));
|
||||
window.close();
|
||||
ev.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
onReportErrorInteract(ev) {
|
||||
if (ev.type === 'click' || (ev.type === 'keydown' && ev.key === ' ')) {
|
||||
Zotero.getActiveZoteroPane().reportErrors();
|
||||
window.close();
|
||||
}
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
if (this.translation && this.translation.interrupt) {
|
||||
this.translation.interrupt();
|
||||
}
|
||||
},
|
||||
|
||||
updateFocus() {
|
||||
(this.wizard.currentPage.querySelector('radiogroup:not([disabled]),checkbox:not([disabled])') ?? this.wizard.currentPage).focus();
|
||||
},
|
||||
|
||||
async startImport() {
|
||||
this.wizard.canAdvance = false;
|
||||
this.wizard.canRewind = false;
|
||||
|
||||
const linkFiles = document.getElementById('file-handling').selectedItem.id === 'link';
|
||||
const recreateStructure = document.getElementById('recreate-structure').checked;
|
||||
const shouldCreateCollection = document.getElementById('create-collection').checked;
|
||||
const mimeTypes = document.getElementById('import-pdf').checked
|
||||
? ['application/pdf']
|
||||
: [];
|
||||
const fileTypes = document.getElementById('import-other').checked
|
||||
? document.getElementById('other-files').value
|
||||
: null;
|
||||
|
||||
try {
|
||||
let result = await Zotero_File_Interface.importFile({
|
||||
file: this._file,
|
||||
const result = await Zotero_File_Interface.importFile({
|
||||
addToLibraryRoot: !shouldCreateCollection,
|
||||
file: this.file,
|
||||
fileTypes,
|
||||
folder: this.folder,
|
||||
linkFiles,
|
||||
mendeleyCode: this.mendeleyCode,
|
||||
mimeTypes,
|
||||
onBeforeImport: this.onBeforeImport.bind(this),
|
||||
addToLibraryRoot: !document.getElementById('create-collection-checkbox')
|
||||
.hasAttribute('checked'),
|
||||
linkFiles: document.getElementById('file-handling-radio').selectedIndex == 1,
|
||||
mendeleyCode: this._mendeleyCode
|
||||
recreateStructure
|
||||
});
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
const numItems = this.translation.newItems.length;
|
||||
this.skipToDonePage(
|
||||
'file-interface-import-complete',
|
||||
['file-interface-items-were-imported', { numItems }]
|
||||
);
|
||||
}
|
||||
catch (e) {
|
||||
if (e.message == 'Encrypted Mendeley database') {
|
||||
let url = 'https://www.zotero.org/support/kb/mendeley_import';
|
||||
let elem = document.createElement('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);
|
||||
this.skipToDonePage('general.error', [], false, true);
|
||||
}
|
||||
else {
|
||||
this._onDone(
|
||||
Zotero.getString('general.error'),
|
||||
Zotero_File_Interface.makeImportErrorString(this._translation),
|
||||
const translatorLabel = this.translation?.translator?.[0]?.label;
|
||||
this.skipToDonePage(
|
||||
'general.error',
|
||||
translatorLabel
|
||||
? ['file-interface-import-error-translator', { translator: translatorLabel }]
|
||||
: 'file-interface-import-error',
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
92
chrome/content/zotero/import/importWizard.xhtml
Normal file
92
chrome/content/zotero/import/importWizard.xhtml
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload="Zotero_Import_Wizard.init()"
|
||||
>
|
||||
<linkset>
|
||||
<html:link rel="localization" href="zotero.ftl" />
|
||||
</linkset>
|
||||
|
||||
<script src="chrome://global/content/customElements.js"/>
|
||||
<wizard id="import-wizard" class="import-wizard" data-l10n-id="import-wizard" width="600" height="400">
|
||||
<wizardpage pageid="page-start" data-header-label-id="import-where-from">
|
||||
<radiogroup id="import-source-group" align="start">
|
||||
<radio value="file" data-l10n-id="import-source-file" />
|
||||
<radio value="folder" data-l10n-id="import-source-folder" />
|
||||
<radio value="mendeleyOnline" data-l10n-id="import-source-online"
|
||||
data-l10n-args='{"targetApp": "Mendeley Reference Manager"}' />
|
||||
</radiogroup>
|
||||
</wizardpage>
|
||||
<wizardpage
|
||||
pageid="page-mendeley-online-intro"
|
||||
data-header-label-id="import-online-intro-title"
|
||||
>
|
||||
<div
|
||||
class="mendeley-online-intro"
|
||||
data-l10n-id="import-online-intro"
|
||||
data-l10n-args='{"targetAppOnline": "Mendeley Reference Manager", "targetApp": "Mendeley"}'></div>
|
||||
<div
|
||||
class="mendeley-online-intro"
|
||||
data-l10n-id="import-online-intro2"
|
||||
data-l10n-args='{"targetApp": "Mendeley"}'></div>
|
||||
</wizardpage>
|
||||
<wizardpage
|
||||
pageid="page-options"
|
||||
data-header-label-id="import-options"
|
||||
>
|
||||
<div class="options-group" id="page-options-common">
|
||||
<checkbox native="true" id="create-collection" data-l10n-id="import-create-collection" />
|
||||
</div>
|
||||
<div class="options-group" id="page-options-folder-import">
|
||||
<checkbox native="true" id="recreate-structure" data-l10n-id="import-recreate-structure" checked="true" />
|
||||
<h2 class="import-file-types-header" data-l10n-id="import-fileTypes-header"></h2>
|
||||
<fieldset>
|
||||
<div class="page-options-file-type">
|
||||
<checkbox native="true" id="import-pdf" data-l10n-id="import-fileTypes-pdf" checked="true" />
|
||||
</div>
|
||||
<div class="page-options-file-type">
|
||||
<checkbox native="true" id="import-other" />
|
||||
<html:input type="text" id="other-files" data-l10n-id="import-fileTypes-other" />
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="options-group" id="page-options-file-handling">
|
||||
<h2 data-l10n-id="import-file-handling"></h2>
|
||||
<radiogroup id="file-handling" align="start">
|
||||
<radio id="store" data-l10n-id="import-file-handling-store" />
|
||||
<radio id="link" data-l10n-id="import-file-handling-link" />
|
||||
</radiogroup>
|
||||
<div class="page-options-file-handling-description" data-l10n-id="import-fileHandling-description"></div>
|
||||
</div>
|
||||
</wizardpage>
|
||||
<wizardpage pageid="page-progress" data-header-label-id="import-importing">
|
||||
<html:progress id="import-progress" max="100" value="0" />
|
||||
<div id="progress-queue-container" class="progress-queue table-container">
|
||||
<div id="progress-queue"></div>
|
||||
</div>
|
||||
</wizardpage>
|
||||
<wizardpage pageid="page-done">
|
||||
<div id="page-done-description"></div>
|
||||
<div id="page-done-error-mendeley" data-l10n-id="import-mendeley-encrypted">
|
||||
<html:a data-l10n-name="mendeley-import-kb" href="https://www.zotero.org/support/kb/mendeley_import" />
|
||||
</div>
|
||||
<div id="page-done-error">
|
||||
<button data-l10n-id="report-error" />
|
||||
</div>
|
||||
<div id="page-done-progress-queue"></div>
|
||||
<div id="done-queue-container" class="done-queue table-container">
|
||||
<div id="done-queue"></div>
|
||||
</div>
|
||||
</wizardpage>
|
||||
</wizard>
|
||||
|
||||
<script src="chrome://zotero/content/include.js"/>
|
||||
<script src="../fileInterface.js"/>
|
||||
<script src="./importWizard.js" />
|
||||
</window>
|
|
@ -1,98 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://zotero/skin/importWizard.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||
|
||||
<wizard id="import-wizard"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
title="&zotero.import;"
|
||||
onwizardcancel="Zotero_Import_Wizard.onCancel()"
|
||||
onload="Zotero_Import_Wizard.init()">
|
||||
|
||||
<script src="../include.js"/>
|
||||
<script src="../fileInterface.js"/>
|
||||
<script src="importWizard.js"/>
|
||||
|
||||
<wizardpage pageid="page-start"
|
||||
label="&zotero.import.whereToImportFrom;"
|
||||
next="page-options"
|
||||
onpageadvanced="Zotero_Import_Wizard.onModeChosen(); return false;">
|
||||
<radiogroup id="import-source">
|
||||
<radio id="radio-import-source-file" label="&zotero.import.source.file;"/>
|
||||
<radio id="radio-import-source-mendeley-online"/>
|
||||
<radio id="radio-import-source-mendeley" hidden="true"/>
|
||||
</radiogroup>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage
|
||||
next="page-options"
|
||||
pageid="mendeley-online-explanation"
|
||||
onpageshow="Zotero_Import_Wizard.onMendeleyOnlineShow()"
|
||||
onpageadvanced="Zotero_Import_Wizard.onMendeleyOnlineAdvance(); return false;"
|
||||
onpagerewound="return Zotero_Import_Wizard.goToStart()"
|
||||
>
|
||||
<description id="mendeley-online-description" />
|
||||
<description id="mendeley-online-description2" />
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage pageid="page-file-list"
|
||||
next="page-options"
|
||||
onpagerewound="return Zotero_Import_Wizard.goToStart()">
|
||||
<description id="file-options-header"/>
|
||||
<listbox id="file-list" onselect="Zotero_Import_Wizard.onFileSelected()">
|
||||
<listhead>
|
||||
<listheader label="&zotero.import.database;"/>
|
||||
<listheader label="&zotero.import.lastModified;"/>
|
||||
<listheader label="&zotero.import.size;"/>
|
||||
</listhead>
|
||||
|
||||
<listcols>
|
||||
<listcol flex="1"/>
|
||||
<listcol/>
|
||||
<listcol/>
|
||||
</listcols>
|
||||
</listbox>
|
||||
<hbox>
|
||||
<button label="&zotero.general.other;" oncommand="Zotero_Import_Wizard.chooseMendeleyDB()"/>
|
||||
</hbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage pageid="page-options"
|
||||
label="&zotero.general.options;"
|
||||
next="page-progress"
|
||||
onpageshow="Zotero_Import_Wizard.onOptionsShown()"
|
||||
onpagerewound="return Zotero_Import_Wizard.goToStart()"
|
||||
onpageadvanced="Zotero_Import_Wizard.onImportStart()">
|
||||
<checkbox id="create-collection-checkbox" label="&zotero.import.createCollection;" checked="true" />
|
||||
|
||||
<vbox id="file-handling-options">
|
||||
<label control="file-handling-radio" value="&zotero.import.fileHandling;"/>
|
||||
<radiogroup id="file-handling-radio">
|
||||
<radio id="file-handling-store" selected="true"/>
|
||||
<radio id="file-handling-link"/>
|
||||
</radiogroup>
|
||||
<description id="file-handling-description"/>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage pageid="page-progress"
|
||||
label="&zotero.import.importing;"
|
||||
onpageshow="document.getElementById('import-wizard').canRewind = false;"
|
||||
next="page-done">
|
||||
<progressmeter id="import-progressmeter" mode="determined"/>
|
||||
</wizardpage>
|
||||
|
||||
<wizardpage pageid="page-done">
|
||||
<description id="result-description"/>
|
||||
<html:div id="result-description-html"/>
|
||||
<hbox>
|
||||
<button id="result-report-error"
|
||||
oncommand="Zotero_Import_Wizard.reportError()"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
</wizardpage>
|
||||
</wizard>
|
47
chrome/content/zotero/import/mendeley/authViewer.js
Normal file
47
chrome/content/zotero/import/mendeley/authViewer.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
Services.scriptloader.loadSubScript("chrome://zotero/content/fileInterface.js", window);
|
||||
const { E10SUtils } = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
|
||||
const URI = `https://api.mendeley.com/oauth/authorize?client_id=5907&redirect_uri=https%3A%2F%2Fzotero-static.s3.amazonaws.com%2Fmendeley_oauth_redirect.html&response_type=code&state=&scope=all`;
|
||||
var startTime;
|
||||
|
||||
const tryExtractAuthCode = browser => {
|
||||
const matchResult = browser.webNavigation.currentURI.spec
|
||||
.match(/mendeley_oauth_redirect.html(?:.*?)(?:\?|&)code=(.*?)(?:&|$)/i);
|
||||
return matchResult ? matchResult[1] : false;
|
||||
}
|
||||
|
||||
const clearCookies = since => {
|
||||
const cookieManager = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
|
||||
const sinceμs = since * 1000;
|
||||
const cookiesSince = cookieManager.getCookiesSince(sinceμs);
|
||||
Zotero.debug(`Deleting ${cookiesSince.length} cookies created during Mendeley Auth (last ${(Date.now() - since)}ms)`);
|
||||
cookieManager.removeAllSince(sinceμs);
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('unload', () => {
|
||||
clearCookies(startTime);
|
||||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
// basicViewer uses remote="false" browser, we need to re-construct the browser so it's
|
||||
// capable of loading a mendeley auth website
|
||||
const browser = document.querySelector('browser');
|
||||
browser.setAttribute('remote', 'true');
|
||||
browser.changeRemoteness({ remoteType: E10SUtils.DEFAULT_REMOTE_TYPE });
|
||||
browser.construct();
|
||||
|
||||
startTime = Date.now();
|
||||
|
||||
browser.addEventListener("pagetitlechanged", event => {
|
||||
const mendeleyCode = tryExtractAuthCode(browser);
|
||||
if (mendeleyCode) {
|
||||
window.close();
|
||||
Zotero_File_Interface.showImportWizard({ mendeleyCode })
|
||||
}
|
||||
document.title = browser.contentTitle;
|
||||
});
|
||||
|
||||
browser.loadURI(URI, {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
}, false);
|
|
@ -60,8 +60,13 @@
|
|||
if (Zotero.isMac) {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
|
||||
}
|
||||
if(window.arguments?.[0] === 'mendeleyImport') {
|
||||
Services.scriptloader.loadSubScript("chrome://zotero/content/import/mendeley/authViewer.js", this);
|
||||
} else {
|
||||
Services.scriptloader.loadSubScript("chrome://zotero/content/standalone/basicViewer.js", this);
|
||||
}
|
||||
|
||||
|
||||
Services.scriptloader.loadSubScript("chrome://zotero/content/standalone/basicViewer.js", this);
|
||||
</script>
|
||||
|
||||
<commandset id="mainCommandSet">
|
||||
|
@ -165,6 +170,13 @@
|
|||
</toolbox>
|
||||
|
||||
<hbox flex="1" id="browser">
|
||||
<vbox id="appcontent" flex="1"/>
|
||||
<vbox id="appcontent" flex="1">
|
||||
<browser
|
||||
type="content"
|
||||
flex="1"
|
||||
remote="false"
|
||||
disableglobalhistory="true"
|
||||
maychangeremoteness="true"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</window>
|
||||
|
|
|
@ -180,6 +180,8 @@
|
|||
<!ENTITY zotero.import "Import">
|
||||
<!ENTITY zotero.import.whereToImportFrom "Where do you want to import from?">
|
||||
<!ENTITY zotero.import.source.file "A file (BibTeX, RIS, Zotero RDF, etc.)">
|
||||
<!ENTITY zotero.import.source.folder "A folder of PDFs or other files">
|
||||
<!ENTITY zotero.import.onlineImport "online import">
|
||||
<!ENTITY zotero.import.importing "Importing…">
|
||||
<!ENTITY zotero.import.database "Database">
|
||||
<!ENTITY zotero.import.lastModified "Last Modified">
|
||||
|
|
64
chrome/locale/en-US/zotero/zotero.ftl
Normal file
64
chrome/locale/en-US/zotero/zotero.ftl
Normal file
|
@ -0,0 +1,64 @@
|
|||
-app-name = Zotero
|
||||
|
||||
import-wizard =
|
||||
.title = "Import"
|
||||
|
||||
import-where-from = Where do you want to import from?
|
||||
import-online-intro-title = Introduction
|
||||
|
||||
import-source-file =
|
||||
.label = A file (BibTeX, RIS, Zotero RDF, etc.)
|
||||
|
||||
import-source-folder =
|
||||
.label = A folder of PDFs or other files
|
||||
|
||||
import-source-online =
|
||||
.label = { $targetApp } online import
|
||||
|
||||
import-options = Options
|
||||
import-importing = Importing…
|
||||
|
||||
import-create-collection =
|
||||
.label = Place imported collections and items into new collection
|
||||
|
||||
import-recreate-structure =
|
||||
.label = Recreate folder structure as collections
|
||||
|
||||
import-fileTypes-header = File Types to Import:
|
||||
|
||||
import-fileTypes-pdf =
|
||||
.label = PDFs
|
||||
|
||||
import-fileTypes-other =
|
||||
.placeholder = Other files by pattern, comma-separated (e.g., *.jpg,*.png)
|
||||
|
||||
import-file-handling = File Handling
|
||||
import-file-handling-store =
|
||||
.label = Copy files to the { -app-name } storage folder
|
||||
import-file-handling-link =
|
||||
.label = Link to files in original location
|
||||
import-fileHandling-description = Linked files cannot be synced by { -app-name }.
|
||||
|
||||
general-error = Error
|
||||
file-interface-import-error = An error occurred while trying to import the selected file. Please ensure that the file is valid and try again.
|
||||
file-interface-import-complete = Import Complete
|
||||
file-interface-items-were-imported = { $numItems ->
|
||||
[one] item was imported
|
||||
*[other] { $numItems } items were imported
|
||||
}
|
||||
|
||||
import-mendeley-encrypted = The selected Mendeley database cannot be read, likely because it is encrypted.
|
||||
See <a data-l10n-name="mendeley-import-kb">How do I import a Mendeley library into Zotero?</a> for more information.
|
||||
|
||||
|
||||
file-interface-import-error = = An error occurred while trying to import the selected file. Please ensure that the file is valid and try again.
|
||||
file-interface-import-error-translator = An error occurred importing the selected file with “{ $translator }”. Please ensure that the file is valid and try again.
|
||||
|
||||
# Variables:
|
||||
# $targetAppOnline (String)
|
||||
# $targetApp (String)
|
||||
import-online-intro=In the next step you will be asked to log in to { $targetAppOnline } and grant { -app-name } access. This is necessary to import your { $targetApp } library into { -app-name }.
|
||||
import-online-intro2={ -app-name } will never see or store your { $targetApp } password.
|
||||
|
||||
report-error =
|
||||
.label = Report Error…
|
|
@ -808,14 +808,6 @@ fileInterface.exportError = An error occurred while trying to export the selecte
|
|||
fileInterface.importOPML = Import Feeds from OPML
|
||||
fileInterface.OPMLFeedFilter = OPML Feed List
|
||||
|
||||
import.onlineImport = online import
|
||||
import.localImport = local import
|
||||
import.fileHandling.store = Copy files to the %S storage folder
|
||||
import.fileHandling.link = Link to files in original location
|
||||
import.fileHandling.description = Linked files cannot be synced by %S.
|
||||
import.online.intro = In the next step you will be asked to log in to %2$S and grant %1$S access. This is necessary to import your %3$S library into %1$S.
|
||||
import.online.intro2 = %1$S will never see or store your %2$S password.
|
||||
|
||||
quickCopy.copyAs = Copy as %S
|
||||
|
||||
quickSearch.mode.titleCreatorYear = Title, Creator, Year
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
.wizard-header-label {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Start */
|
||||
wizard[currentpageid="page-start"] .wizard-header-label {
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
wizard[currentpageid="page-start"] .wizard-page-box {
|
||||
margin-top: -2px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
radiogroup {
|
||||
font-size: 14px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
radio {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
/* File list */
|
||||
wizard[currentpageid="page-file-list"] .wizard-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#file-options-header {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
#file-handling-options {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#file-handling-options > label {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#file-handling-options radiogroup {
|
||||
font-size: 13px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
#file-handling-options description {
|
||||
margin-top: .6em;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
listbox, #result-description, #result-description-html {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#result-description-html {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#mendeley-online-description, #mendeley-online-description2 {
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#mendeley-online-description2 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#result-description-html a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
button, checkbox {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#result-report-error {
|
||||
margin-top: 13px;
|
||||
margin-left: 0;
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
@import "components/editable";
|
||||
@import "components/exportOptions";
|
||||
@import "components/icons";
|
||||
@import "components/import-wizard";
|
||||
@import "components/item-tree";
|
||||
@import "components/longTagFixer";
|
||||
@import "components/mainWindow";
|
||||
|
|
142
scss/components/_import-wizard.scss
Normal file
142
scss/components/_import-wizard.scss
Normal file
|
@ -0,0 +1,142 @@
|
|||
.import-wizard {
|
||||
font-size: 12px;
|
||||
|
||||
radiogroup {
|
||||
radio {
|
||||
padding-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
wizardpage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline;
|
||||
color: -moz-nativehyperlinktext;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
outline:none;
|
||||
text-decoration: $link-hover-decoration;
|
||||
}
|
||||
}
|
||||
|
||||
checkbox {
|
||||
margin-left: 4px; // indent required for correct focus ring rendering
|
||||
}
|
||||
|
||||
button {
|
||||
font: menu;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#other-files {
|
||||
margin-left: -1px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
|
||||
#page-start {
|
||||
radiogroup {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
#page-options-folder-import {
|
||||
fieldset {
|
||||
display: block;
|
||||
border: none;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
#recreate-structure {
|
||||
margin-top: .25em;
|
||||
}
|
||||
|
||||
.import-file-types-header {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.page-options-file-type {
|
||||
display: flex;
|
||||
margin-top: .25em;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#page-options-file-handling {
|
||||
padding-top: 1.5em;
|
||||
|
||||
.radioset {
|
||||
// font-size: 13px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.page-options-file-handling-description {
|
||||
margin-top: .6em;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#page-done-error {
|
||||
margin-top: 2em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.mendeley-online-intro {
|
||||
// font-size: 13px;
|
||||
|
||||
& +.mendeley-online-intro {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
#import-progress {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#page-progress {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// TODO: deduplicate with rtfscan
|
||||
.table-container {
|
||||
display: flex;
|
||||
height: 0;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
margin-top: 1.5em;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
background-color: -moz-field;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.virtualized-table-body {
|
||||
display: flex;
|
||||
|
||||
.windowed-list {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
describe('Zotero_Import_Folder', function () {
|
||||
var tmpDir;
|
||||
const uc = (name) => 'Zotero_Import_Folder_' + name;
|
||||
const uc = name => 'Zotero_Import_Folder_' + name;
|
||||
|
||||
before(async () => {
|
||||
tmpDir = await getTempDirectory();
|
||||
|
@ -111,7 +111,7 @@ describe('Zotero_Import_Folder', function () {
|
|||
const importer = new Zotero_Import_Folder({
|
||||
folder: tmpDir,
|
||||
recreateStructure: false,
|
||||
fileTypes: '*.png,*.txt',
|
||||
fileTypes: '*.png,*.TXT', // should match case-insensitively
|
||||
mimeTypes: []
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue