changed import progress notification so it shows up for drag & drop as well

This commit is contained in:
zadam
2019-10-14 10:31:58 +02:00
parent 2fb3a3eff9
commit 2ee94a3a69
14 changed files with 136 additions and 134 deletions

View File

@@ -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;

View File

@@ -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");

View File

@@ -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,

View 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
}

View File

@@ -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) {

View File

@@ -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,

View File

@@ -1,5 +1,6 @@
import utils from './utils.js';
import infoService from "./info.js";
import treeService from "./tree.js";
const $outstandingSyncsCount = $("#outstanding-syncs-count");

View File

@@ -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();

View File

@@ -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];
}

View File

@@ -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;

View File

@@ -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>