mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
allow import of multiple files at the same time
This commit is contained in:
parent
936f85c09e
commit
886ea6c68c
@ -43,27 +43,45 @@ $form.submit(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
function importIntoNote(importNoteId) {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', $fileUploadInput[0].files[0]);
|
||||
async function importIntoNote(importNoteId) {
|
||||
const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
|
||||
|
||||
// we generate it here (and not on opening) for the case when you try to import multiple times from the same
|
||||
// dialog (which shouldn't happen, but still ...)
|
||||
importId = utils.randomString(10);
|
||||
|
||||
const safeImport = $safeImport.is(":checked") ? 1 : 0;
|
||||
let noteId;
|
||||
|
||||
$.ajax({
|
||||
url: baseApiUrl + 'notes/' + importNoteId + '/import/' + importId + '/safe/' + safeImport,
|
||||
headers: server.getHeaders(),
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false, // NEEDED, DON'T REMOVE THIS
|
||||
})
|
||||
for (const file of files) {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', file);
|
||||
|
||||
noteId = await $.ajax({
|
||||
url: baseApiUrl + 'notes/' + importNoteId + '/import/' + importId + '/safe/' + safeImport,
|
||||
headers: server.getHeaders(),
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
timeout: 60 * 60 * 1000,
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false, // NEEDED, DON'T REMOVE THIS
|
||||
})
|
||||
// we actually ignore the error since it can be caused by HTTP timeout and use WS messages instead.
|
||||
.fail((xhr, status, error) => {});
|
||||
.fail((xhr, status, error) => {});
|
||||
}
|
||||
|
||||
$dialog.modal('hide');
|
||||
|
||||
infoService.showMessage("Import finished successfully.");
|
||||
|
||||
await treeService.reload();
|
||||
|
||||
if (noteId) {
|
||||
const node = await treeService.activateNote(noteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
}
|
||||
|
||||
messagingService.subscribeToMessages(async message => {
|
||||
@ -83,19 +101,6 @@ messagingService.subscribeToMessages(async message => {
|
||||
|
||||
$importProgressCount.text(message.progressCount);
|
||||
}
|
||||
else if (message.type === 'import-finished') {
|
||||
$dialog.modal('hide');
|
||||
|
||||
infoService.showMessage("Import finished successfully.");
|
||||
|
||||
await treeService.reload();
|
||||
|
||||
if (message.noteId) {
|
||||
const node = await treeService.activateNote(message.noteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$fileUploadInput.change(() => {
|
||||
|
@ -36,7 +36,7 @@ async function importToBranch(req) {
|
||||
|
||||
let note; // typically root of the import - client can show it after finishing the import
|
||||
|
||||
const importContext = new ImportContext(importId, safeImport);
|
||||
const importContext = ImportContext.getInstance(importId, safeImport);
|
||||
|
||||
try {
|
||||
if (extension === '.tar') {
|
||||
|
@ -298,12 +298,7 @@ async function importEnex(importContext, file, parentNote) {
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
// resolve only when we parse the whole document AND saving of all notes have been finished
|
||||
saxStream.on("end", () => { Promise.all(saveNotePromises).then(() => {
|
||||
importContext.importFinished(rootNote.noteId);
|
||||
|
||||
resolve(rootNote);
|
||||
});
|
||||
});
|
||||
saxStream.on("end", () => { Promise.all(saveNotePromises).then(() => resolve(rootNote)) });
|
||||
|
||||
const bufferStream = new stream.PassThrough();
|
||||
bufferStream.end(file.buffer);
|
||||
|
@ -64,8 +64,6 @@ async function importOpml(importContext, fileBuffer, parentNote) {
|
||||
returnNote = returnNote || note;
|
||||
}
|
||||
|
||||
importContext.importFinished(returnNote.noteId);
|
||||
|
||||
return returnNote;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ async function importMarkdown(importContext, file, parentNote) {
|
||||
});
|
||||
|
||||
importContext.increaseProgressCount();
|
||||
importContext.importFinished(note.noteId);
|
||||
|
||||
return note;
|
||||
}
|
||||
@ -36,7 +35,6 @@ async function importHtml(importContext, file, parentNote) {
|
||||
});
|
||||
|
||||
importContext.increaseProgressCount();
|
||||
importContext.importFinished(note.noteId);
|
||||
|
||||
return note;
|
||||
}
|
||||
|
@ -386,8 +386,6 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
}
|
||||
}
|
||||
|
||||
importContext.importFinished();
|
||||
|
||||
resolve(firstNote);
|
||||
});
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
const messagingService = require('./messaging');
|
||||
|
||||
// importId => ImportContext
|
||||
const importContexts = {};
|
||||
|
||||
class ImportContext {
|
||||
constructor(importId, safeImport) {
|
||||
// importId is to distinguish between different import events - it is possible (though not recommended)
|
||||
@ -15,6 +18,15 @@ class ImportContext {
|
||||
this.lastSentCountTs = Date.now();
|
||||
}
|
||||
|
||||
/** @return {ImportContext} */
|
||||
static getInstance(importId, safeImport) {
|
||||
if (!importContexts[importId]) {
|
||||
importContexts[importId] = new ImportContext(importId, safeImport);
|
||||
}
|
||||
|
||||
return importContexts[importId];
|
||||
}
|
||||
|
||||
async increaseProgressCount() {
|
||||
this.progressCount++;
|
||||
|
||||
@ -29,14 +41,6 @@ class ImportContext {
|
||||
}
|
||||
}
|
||||
|
||||
async importFinished(noteId) {
|
||||
await messagingService.sendMessageToAllClients({
|
||||
importId: this.importId,
|
||||
type: 'import-finished',
|
||||
noteId: noteId
|
||||
});
|
||||
}
|
||||
|
||||
// must remaing non-static
|
||||
async reportError(message) {
|
||||
await messagingService.sendMessageToAllClients({
|
||||
|
@ -16,7 +16,7 @@
|
||||
<div class="form-group">
|
||||
<label for="import-file-upload-input"><strong>Choose import file</strong></label>
|
||||
|
||||
<input type="file" id="import-file-upload-input" class="form-control-file" />
|
||||
<input type="file" id="import-file-upload-input" class="form-control-file" multiple />
|
||||
|
||||
<p>Content of the file will be imported as child note(s) into <strong class="note-title"></strong>. Import file must be of supported type and have correct extension - one of <code>.html</code>, <code>.md</code>, <code>.tar</code>, <code>.enex</code>.</p>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user