www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

importWizard.js (9146B)


      1 var Zotero_Import_Wizard = {
      2 	_wizard: null,
      3 	_dbs: null,
      4 	_file: null,
      5 	_translation: null,
      6 	
      7 	
      8 	init: async function () {
      9 		this._wizard = document.getElementById('import-wizard');
     10 		
     11 		var dbs = await Zotero_File_Interface.findMendeleyDatabases();
     12 		if (dbs.length) {
     13 			document.getElementById('radio-import-source-mendeley').hidden = false;
     14 		}
     15 		
     16 		// If no existing collections or non-trash items in the library, don't create a new
     17 		// collection by default
     18 		var args = window.arguments[0].wrappedJSObject;
     19 		if (args && args.libraryID) {
     20 			let sql = "SELECT ROWID FROM collections WHERE libraryID=?1 "
     21 				+ "UNION "
     22 				+ "SELECT ROWID FROM items WHERE libraryID=?1 "
     23 				// Not in trash
     24 				+ "AND itemID NOT IN (SELECT itemID FROM deletedItems) "
     25 				// And not a child item (which doesn't necessarily show up in the trash)
     26 				+ "AND itemID NOT IN (SELECT itemID FROM itemNotes WHERE parentItemID IS NOT NULL) "
     27 				+ "AND itemID NOT IN (SELECT itemID FROM itemAttachments WHERE parentItemID IS NOT NULL) "
     28 				+ "LIMIT 1";
     29 			if (!await Zotero.DB.valueQueryAsync(sql, args.libraryID)) {
     30 				document.getElementById('create-collection-checkbox').removeAttribute('checked');
     31 			}
     32 		}
     33 		
     34 		Zotero.Translators.init(); // async
     35 	},
     36 	
     37 	
     38 	onModeChosen: async function () {
     39 		var wizard = this._wizard;
     40 		
     41 		var mode = document.getElementById('import-source').selectedItem.id;
     42 		try {
     43 			switch (mode) {
     44 			case 'radio-import-source-file':
     45 				await this.chooseFile();
     46 				break;
     47 				
     48 			case 'radio-import-source-mendeley':
     49 				this._dbs = await Zotero_File_Interface.findMendeleyDatabases();
     50 				// This shouldn't happen, because we only show the wizard if there are databases
     51 				if (!this._dbs.length) {
     52 					throw new Error("No databases found");
     53 				}
     54 				this._populateFileList(this._dbs);
     55 				document.getElementById('file-options-header').textContent
     56 					= Zotero.getString('fileInterface.chooseAppDatabaseToImport', 'Mendeley')
     57 				wizard.goTo('page-file-list');
     58 				wizard.canRewind = true;
     59 				this._enableCancel();
     60 				break;
     61 			
     62 			default:
     63 				throw new Error(`Unknown mode ${mode}`);
     64 			}
     65 		}
     66 		catch (e) {
     67 			this._onDone(
     68 				Zotero.getString('general.error'),
     69 				Zotero.getString('fileInterface.importError'),
     70 				true
     71 			);
     72 			throw e;
     73 		}
     74 	},
     75 	
     76 	
     77 	goToStart: function () {
     78 		this._wizard.goTo('page-start');
     79 		this._wizard.canAdvance = true;
     80 		return false;
     81 	},
     82 	
     83 	
     84 	chooseFile: async function (translation) {
     85 		var translation = new Zotero.Translate.Import();
     86 		var translators = await translation.getTranslators();
     87 		const nsIFilePicker = Components.interfaces.nsIFilePicker;
     88 		var fp = Components.classes["@mozilla.org/filepicker;1"]
     89 				.createInstance(nsIFilePicker);
     90 		fp.init(window, Zotero.getString("fileInterface.import"), nsIFilePicker.modeOpen);
     91 		
     92 		fp.appendFilters(nsIFilePicker.filterAll);
     93 		
     94 		var collation = Zotero.getLocaleCollation();
     95 		
     96 		// Add Mendeley DB, which isn't a translator
     97 		var mendeleyFilter = {
     98 			label: "Mendeley Database", // TODO: Localize
     99 			target: "*.sqlite"
    100 		};
    101 		var filters = [...translators];
    102 		filters.push(mendeleyFilter);
    103 		
    104 		filters.sort((a, b) => collation.compareString(1, a.label, b.label));
    105 		for (let filter of filters) {
    106 			fp.appendFilter(filter.label, "*." + filter.target);
    107 		}
    108 		
    109 		var rv = fp.show();
    110 		if (rv !== nsIFilePicker.returnOK && rv !== nsIFilePicker.returnReplace) {
    111 			return false;
    112 		}
    113 		
    114 		Zotero.debug(`File is ${fp.file.path}`);
    115 		
    116 		this._file = fp.file.path;
    117 		this._wizard.canAdvance = true;
    118 		this._wizard.goTo('page-options');
    119 	},
    120 	
    121 	
    122 	/**
    123 	 * When a file is clicked on in the file list
    124 	 */
    125 	onFileSelected: async function () {
    126 		var index = document.getElementById('file-list').selectedIndex;
    127 		if (index != -1) {
    128 			this._file = this._dbs[index].path;
    129 			this._wizard.canAdvance = true;
    130 		}
    131 		else {
    132 			this._file = null;
    133 			this._wizard.canAdvance = false;
    134 		}
    135 	},
    136 	
    137 	
    138 	/**
    139 	 * When the user clicks "Other…" to choose a file not in the list
    140 	 */
    141 	chooseMendeleyDB: async function () {
    142 		document.getElementById('file-list').selectedIndex = -1;
    143 		const nsIFilePicker = Components.interfaces.nsIFilePicker;
    144 		var fp = Components.classes["@mozilla.org/filepicker;1"]
    145 			.createInstance(nsIFilePicker);
    146 		fp.init(window, Zotero.getString('fileInterface.import'), nsIFilePicker.modeOpen);
    147 		fp.appendFilter("Mendeley Database", "*.sqlite"); // TODO: Localize
    148 		var rv = fp.show();
    149 		if (rv != nsIFilePicker.returnOK) {
    150 			return false;
    151 		}
    152 		this._file = fp.file.path;
    153 		this._wizard.canAdvance = true;
    154 		this._wizard.advance();
    155 	},
    156 	
    157 	
    158 	onOptionsShown: function () {
    159 		
    160 	},
    161 	
    162 	
    163 	onImportStart: async function () {
    164 		if (!this._file) {
    165 			let index = document.getElementById('file-list').selectedIndex;
    166 			this._file = this._dbs[index].path;
    167 		}
    168 		this._disableCancel();
    169 		this._wizard.canRewind = false;
    170 		this._wizard.canAdvance = false;
    171 		await this.doImport({
    172 			createNewCollection: document.getElementById('create-collection-checkbox').hasAttribute('checked')
    173 		});
    174 	},
    175 	
    176 	
    177 	onBeforeImport: async function (translation) {
    178 		// Unrecognized translator
    179 		if (!translation) {
    180 			// Allow error dialog to be displayed, and then close window
    181 			setTimeout(function () {
    182 				window.close();
    183 			});
    184 			return;
    185 		}
    186 		
    187 		this._translation = translation;
    188 		
    189 		// Switch to progress pane
    190 		this._wizard.goTo('page-progress');
    191 		var pm = document.getElementById('import-progressmeter');
    192 		
    193 		translation.setHandler('itemDone', function () {
    194 			pm.value = translation.getProgress();
    195 		});
    196 	},
    197 	
    198 	
    199 	doImport: async function (options) {
    200 		try {
    201 			let result = await Zotero_File_Interface.importFile({
    202 				file: this._file,
    203 				onBeforeImport: this.onBeforeImport.bind(this),
    204 				addToLibraryRoot: !options.createNewCollection
    205 			});
    206 			
    207 			// Cancelled by user or due to error
    208 			if (!result) {
    209 				window.close();
    210 				return;
    211 			}
    212 			
    213 			let numItems = this._translation.newItems.length;
    214 			this._onDone(
    215 				Zotero.getString('fileInterface.importComplete'),
    216 				Zotero.getString(`fileInterface.itemsWereImported`, numItems, numItems)
    217 			);
    218 		}
    219 		catch (e) {
    220 			if (e.message == 'Encrypted Mendeley database') {
    221 				let url = 'https://www.zotero.org/support/kb/mendeley_import';
    222 				this._onDone(
    223 					Zotero.getString('general.error'),
    224 					// TODO: Localize
    225 					`The selected Mendeley database cannot be read, likely because it is encrypted. `
    226 						+ `See <a href="${url}" class="text-link">How do I import a Mendeley library `
    227 						+ `into Zotero?</a> for more information.`
    228 				);
    229 			}
    230 			else {
    231 				this._onDone(
    232 					Zotero.getString('general.error'),
    233 					Zotero.getString('fileInterface.importError'),
    234 					true
    235 				);
    236 			}
    237 			throw e;
    238 		}
    239 	},
    240 	
    241 	
    242 	reportError: function () {
    243 		Zotero.getActiveZoteroPane().reportErrors();
    244 		window.close();
    245 	},
    246 	
    247 	
    248 	_populateFileList: async function (files) {
    249 		var listbox = document.getElementById('file-list');
    250 		
    251 		// Remove existing entries
    252 		var items = listbox.getElementsByTagName('listitem');
    253 		for (let item of items) {
    254 			listbox.removeChild(item);
    255 		}
    256 		
    257 		for (let file of files) {
    258 			let li = document.createElement('listitem');
    259 			
    260 			let name = document.createElement('listcell');
    261 			// Simply filenames
    262 			let nameStr = file.name
    263 				.replace(/\.sqlite$/, '')
    264 				.replace(/@www\.mendeley\.com$/, '');
    265 			if (nameStr == 'online') {
    266 				nameStr = Zotero.getString('dataDir.default', 'online.sqlite');
    267 			}
    268 			name.setAttribute('label', nameStr + ' ');
    269 			li.appendChild(name);
    270 			
    271 			let lastModified = document.createElement('listcell');
    272 			lastModified.setAttribute('label', file.lastModified.toLocaleString() + ' ');
    273 			li.appendChild(lastModified);
    274 			
    275 			let size = document.createElement('listcell');
    276 			size.setAttribute(
    277 				'label',
    278 				Zotero.getString('general.nMegabytes', (file.size / 1024 / 1024).toFixed(1)) + ' '
    279 			);
    280 			li.appendChild(size);
    281 			
    282 			listbox.appendChild(li);
    283 		}
    284 		
    285 		if (files.length == 1) {
    286 			listbox.selectedIndex = 0;
    287 		}
    288 	},
    289 	
    290 	
    291 	_enableCancel: function () {
    292 		this._wizard.getButton('cancel').disabled = false;
    293 	},
    294 	
    295 	
    296 	_disableCancel: function () {
    297 		this._wizard.getButton('cancel').disabled = true;
    298 	},
    299 	
    300 	
    301 	_onDone: function (label, description, showReportErrorButton) {
    302 		var wizard = this._wizard;
    303 		wizard.getPageById('page-done').setAttribute('label', label);
    304 		
    305 		var xulElem = document.getElementById('result-description');
    306 		var htmlElem = document.getElementById('result-description-html');
    307 		
    308 		if (description.includes('href')) {
    309 			htmlElem.innerHTML = description;
    310 			Zotero.Utilities.Internal.updateHTMLInXUL(htmlElem);
    311 			xulElem.hidden = true;
    312 			htmlElem.setAttribute('display', 'block');
    313 		}
    314 		else {
    315 			xulElem.textContent = description;
    316 			xulElem.hidden = false;
    317 			htmlElem.setAttribute('display', 'none');
    318 		}
    319 		document.getElementById('result-description')
    320 		
    321 		if (showReportErrorButton) {
    322 			let button = document.getElementById('result-report-error');
    323 			button.setAttribute('label', Zotero.getString('errorReport.reportError'));
    324 			button.hidden = false;
    325 		}
    326 		
    327 		// When done, move to last page and allow closing
    328 		wizard.canAdvance = true;
    329 		wizard.goTo('page-done');
    330 		wizard.canRewind = false;
    331 	}
    332 };