mirror of
https://github.com/zadam/trilium.git
synced 2025-11-04 20:36:13 +01:00
changed import progress notification so it shows up for drag & drop as well
This commit is contained in:
@@ -29,6 +29,7 @@ import macInit from './services/mac_init.js';
|
||||
import cssLoader from './services/css_loader.js';
|
||||
import dateNoteService from './services/date_notes.js';
|
||||
import sidebarService from './services/sidebar.js';
|
||||
import importService from './services/import.js';
|
||||
|
||||
window.glob.isDesktop = utils.isDesktop;
|
||||
window.glob.isMobile = utils.isMobile;
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import treeService from '../services/tree.js';
|
||||
import utils from '../services/utils.js';
|
||||
import treeUtils from "../services/tree_utils.js";
|
||||
import server from "../services/server.js";
|
||||
import infoService from "../services/info.js";
|
||||
import ws from "../services/ws.js";
|
||||
import importService from "../services/import.js";
|
||||
|
||||
const $dialog = $("#import-dialog");
|
||||
const $form = $("#import-form");
|
||||
const $noteTitle = $dialog.find(".import-note-title");
|
||||
const $fileUploadInput = $("#import-file-upload-input");
|
||||
const $importProgressCountWrapper = $("#import-progress-count-wrapper");
|
||||
const $importProgressCount = $("#import-progress-count");
|
||||
const $importButton = $("#import-button");
|
||||
const $safeImportCheckbox = $("#safe-import-checkbox");
|
||||
const $shrinkImagesCheckbox = $("#shrink-images-checkbox");
|
||||
@@ -18,16 +13,11 @@ const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox");
|
||||
const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox");
|
||||
const $explodeArchivesCheckbox = $("#explode-archives-checkbox");
|
||||
|
||||
let importId;
|
||||
let importIntoNoteId = null;
|
||||
let parentNoteId = null;
|
||||
|
||||
export async function showDialog(node) {
|
||||
utils.closeActiveDialog();
|
||||
|
||||
// each opening of the dialog resets the importId so we don't associate it with previous imports anymore
|
||||
importId = '';
|
||||
$importProgressCountWrapper.hide();
|
||||
$importProgressCount.text('0');
|
||||
$fileUploadInput.val('').change(); // to trigger Import button disabling listener below
|
||||
|
||||
$safeImportCheckbox.prop("checked", true);
|
||||
@@ -38,9 +28,9 @@ export async function showDialog(node) {
|
||||
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
importIntoNoteId = node.data.noteId;
|
||||
parentNoteId = node.data.noteId;
|
||||
|
||||
$noteTitle.text(await treeUtils.getNoteTitle(importIntoNoteId));
|
||||
$noteTitle.text(await treeUtils.getNoteTitle(parentNoteId));
|
||||
|
||||
$dialog.modal();
|
||||
}
|
||||
@@ -49,18 +39,14 @@ $form.submit(() => {
|
||||
// disabling so that import is not triggered again.
|
||||
$importButton.attr("disabled", "disabled");
|
||||
|
||||
importIntoNote(importIntoNoteId);
|
||||
importIntoNote(parentNoteId);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
async function importIntoNote(importNoteId) {
|
||||
async function importIntoNote(parentNoteId) {
|
||||
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 options = {
|
||||
safeImport: boolToString($safeImportCheckbox),
|
||||
shrinkImages: boolToString($shrinkImagesCheckbox),
|
||||
@@ -69,73 +55,15 @@ async function importIntoNote(importNoteId) {
|
||||
explodeArchives: boolToString($explodeArchivesCheckbox)
|
||||
};
|
||||
|
||||
await uploadFiles(importNoteId, files, options);
|
||||
|
||||
$dialog.modal('hide');
|
||||
}
|
||||
|
||||
export async function uploadFiles(importNoteId, files, options) {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let noteId;
|
||||
|
||||
for (const file of files) {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', file);
|
||||
formData.append('importId', importId);
|
||||
|
||||
for (const key in options) {
|
||||
formData.append(key, options[key]);
|
||||
}
|
||||
|
||||
({noteId} = await $.ajax({
|
||||
url: baseApiUrl + 'notes/' + importNoteId + '/import',
|
||||
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
|
||||
}));
|
||||
}
|
||||
|
||||
infoService.showMessage("Import finished successfully.");
|
||||
|
||||
await treeService.reloadNote(importNoteId);
|
||||
|
||||
if (noteId) {
|
||||
const node = await treeService.activateNote(noteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
await importService.uploadFiles(parentNoteId, files, options);
|
||||
}
|
||||
|
||||
function boolToString($el) {
|
||||
return $el.is(":checked") ? "true" : "false";
|
||||
}
|
||||
|
||||
ws.subscribeToMessages(async message => {
|
||||
if (message.type === 'import-error') {
|
||||
infoService.showError(message.message);
|
||||
$dialog.modal('hide');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!message.importId || message.importId !== importId) {
|
||||
// incoming messages must correspond to this import instance
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'import-progress-count') {
|
||||
$importProgressCountWrapper.slideDown();
|
||||
|
||||
$importProgressCount.text(message.progressCount);
|
||||
}
|
||||
});
|
||||
|
||||
$fileUploadInput.change(() => {
|
||||
if ($fileUploadInput.val()) {
|
||||
$importButton.removeAttr("disabled");
|
||||
|
||||
@@ -30,9 +30,9 @@ const dragAndDropSetup = {
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||
|
||||
const importDialog = await import('../dialogs/import.js');
|
||||
const importService = await import('./import.js');
|
||||
|
||||
importDialog.uploadFiles(node.data.noteId, files, {
|
||||
importService.uploadFiles(node.data.noteId, files, {
|
||||
safeImport: true,
|
||||
shrinkImages: true,
|
||||
textImportedAsText: true,
|
||||
|
||||
66
src/public/javascripts/services/import.js
Normal file
66
src/public/javascripts/services/import.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import infoService from "./info.js";
|
||||
import treeService from "./tree.js";
|
||||
import server from "./server.js";
|
||||
import ws from "./ws.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
export async function uploadFiles(parentNoteId, files, options) {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importId = utils.randomString(10);
|
||||
let noteId;
|
||||
let counter = 0;
|
||||
|
||||
for (const file of files) {
|
||||
counter++;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('upload', file);
|
||||
formData.append('importId', importId);
|
||||
formData.append('last', counter === files.length ? "true" : "false");
|
||||
|
||||
for (const key in options) {
|
||||
formData.append(key, options[key]);
|
||||
}
|
||||
|
||||
({noteId} = await $.ajax({
|
||||
url: baseApiUrl + 'notes/' + parentNoteId + '/import',
|
||||
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
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ws.subscribeToMessages(async message => {
|
||||
if (message.type === 'import-error') {
|
||||
infoService.showError(message.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'import-progress-count') {
|
||||
infoService.showMessage("Import in progress: " + message.progressCount, 1000);
|
||||
}
|
||||
|
||||
if (message.type === 'import-succeeded') {
|
||||
infoService.showMessage("Import finished successfully.", 5000);
|
||||
|
||||
await treeService.reloadNote(message.parentNoteId);
|
||||
|
||||
if (message.importedNoteId) {
|
||||
const node = await treeService.activateNote(message.importedNoteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
uploadFiles
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import ws from "./ws.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
function showMessage(message) {
|
||||
function showMessage(message, delay = 3000) {
|
||||
console.debug(utils.now(), "message: ", message);
|
||||
|
||||
$.notify({
|
||||
icon: 'jam jam-check',
|
||||
message: message
|
||||
}, getNotifySettings('success', 3000));
|
||||
}, getNotifySettings('success', delay));
|
||||
}
|
||||
|
||||
function showAndLogError(message, delay = 10000) {
|
||||
|
||||
@@ -345,9 +345,9 @@ $tabContentsContainer.on("drop", async e => {
|
||||
|
||||
const files = [...e.originalEvent.dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||
|
||||
const importDialog = await import("../dialogs/import.js");
|
||||
const importService = await import("./import.js");
|
||||
|
||||
importDialog.uploadFiles(activeNote.noteId, files, {
|
||||
importService.uploadFiles(activeNote.noteId, files, {
|
||||
safeImport: true,
|
||||
shrinkImages: true,
|
||||
textImportedAsText: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import utils from './utils.js';
|
||||
import infoService from "./info.js";
|
||||
import treeService from "./tree.js";
|
||||
|
||||
const $outstandingSyncsCount = $("#outstanding-syncs-count");
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const ImportContext = require('../../services/import_context');
|
||||
|
||||
async function importToBranch(req) {
|
||||
const {parentNoteId} = req.params;
|
||||
const {importId} = req.body;
|
||||
const {importId, last} = req.body;
|
||||
|
||||
const options = {
|
||||
safeImport: req.body.safeImport !== 'false',
|
||||
@@ -65,6 +65,11 @@ async function importToBranch(req) {
|
||||
return [500, message];
|
||||
}
|
||||
|
||||
if (last === "true") {
|
||||
// small timeout to avoid race condition (message is received before the transaction is committed)
|
||||
setTimeout(() => importContext.importSucceeded(parentNoteId, note.noteId), 1000);
|
||||
}
|
||||
|
||||
// import has deactivated note events so note cache is not updated
|
||||
// instead we force it to reload (can be async)
|
||||
noteCacheService.load();
|
||||
|
||||
@@ -116,11 +116,7 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
function getNoteId(noteMeta, filePath) {
|
||||
const filePathNoExt = getTextFileWithoutExtension(filePath);
|
||||
|
||||
console.log(`Searching for noteId of filePath ${filePath} with meta: ${!!noteMeta}`);
|
||||
|
||||
if (filePathNoExt in createdPaths) {
|
||||
console.log("Found existing path", filePathNoExt, createdPaths[filePathNoExt]);
|
||||
|
||||
return createdPaths[filePathNoExt];
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class ImportContext {
|
||||
async increaseProgressCount() {
|
||||
this.progressCount++;
|
||||
|
||||
if (Date.now() - this.lastSentCountTs >= 500) {
|
||||
if (Date.now() - this.lastSentCountTs >= 1000) {
|
||||
this.lastSentCountTs = Date.now();
|
||||
|
||||
await ws.sendMessageToAllClients({
|
||||
@@ -51,6 +51,15 @@ class ImportContext {
|
||||
message: message
|
||||
});
|
||||
}
|
||||
|
||||
// must remaing non-static
|
||||
async importSucceeded(parentNoteId, importedNoteId) {
|
||||
await ws.sendMessageToAllClients({
|
||||
type: 'import-succeeded',
|
||||
parentNoteId: parentNoteId,
|
||||
importedNoteId: importedNoteId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ImportContext;
|
||||
@@ -9,10 +9,6 @@
|
||||
</div>
|
||||
<form id="import-form">
|
||||
<div class="modal-body">
|
||||
<div id="import-progress-count-wrapper" class="alert alert-primary" style="padding: 15px;">
|
||||
<strong>Note import progress count:</strong> <span id="import-progress-count"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="import-file-upload-input"><strong>Choose import file</strong></label>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user