You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-07 22:03:09 +02:00
Tools: Enforce and apply eslint rules prefer-const and no-var
This commit is contained in:
@ -54,16 +54,20 @@ module.exports = {
|
|||||||
// This error is always a false positive so far since it detects
|
// This error is always a false positive so far since it detects
|
||||||
// possible race conditions in contexts where we know it cannot happen.
|
// possible race conditions in contexts where we know it cannot happen.
|
||||||
"require-atomic-updates": 0,
|
"require-atomic-updates": 0,
|
||||||
|
"prefer-const": ["error"],
|
||||||
|
"no-var": ["error"],
|
||||||
|
|
||||||
// Checks rules of Hooks
|
// Checks rules of Hooks
|
||||||
"react-hooks/rules-of-hooks": "error",
|
"react-hooks/rules-of-hooks": "error",
|
||||||
// Checks effect dependencies
|
// Checks effect dependencies
|
||||||
"react-hooks/exhaustive-deps": "warn",
|
// Disable because of this: https://github.com/facebook/react/issues/16265
|
||||||
|
// "react-hooks/exhaustive-deps": "warn",
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Formatting
|
// Formatting
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
"space-in-parens": ["error", "never"],
|
"space-in-parens": ["error", "never"],
|
||||||
|
"space-infix-ops": ["error"],
|
||||||
"semi": ["error", "always"],
|
"semi": ["error", "always"],
|
||||||
"eol-last": ["error", "always"],
|
"eol-last": ["error", "always"],
|
||||||
"quotes": ["error", "single"],
|
"quotes": ["error", "single"],
|
||||||
@ -92,7 +96,7 @@ module.exports = {
|
|||||||
"multiline-comment-style": ["error", "separate-lines"],
|
"multiline-comment-style": ["error", "separate-lines"],
|
||||||
"space-before-blocks": "error",
|
"space-before-blocks": "error",
|
||||||
"spaced-comment": ["error", "always"],
|
"spaced-comment": ["error", "always"],
|
||||||
"keyword-spacing": ["error", { "before": true, "after": true }]
|
"keyword-spacing": ["error", { "before": true, "after": true }],
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"react",
|
"react",
|
||||||
|
@ -134,7 +134,7 @@ class AppGui {
|
|||||||
const item = folderList.currentItem;
|
const item = folderList.currentItem;
|
||||||
|
|
||||||
if (item === '-') {
|
if (item === '-') {
|
||||||
let newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1);
|
const newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1);
|
||||||
let nextItem = folderList.itemAt(newIndex);
|
let nextItem = folderList.itemAt(newIndex);
|
||||||
if (!nextItem) nextItem = folderList.itemAt(event.previousIndex);
|
if (!nextItem) nextItem = folderList.itemAt(event.previousIndex);
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ class AppGui {
|
|||||||
borderRightWidth: 1,
|
borderRightWidth: 1,
|
||||||
};
|
};
|
||||||
noteList.on('currentItemChange', async () => {
|
noteList.on('currentItemChange', async () => {
|
||||||
let note = noteList.currentItem;
|
const note = noteList.currentItem;
|
||||||
this.store_.dispatch({
|
this.store_.dispatch({
|
||||||
type: 'NOTE_SELECT',
|
type: 'NOTE_SELECT',
|
||||||
id: note ? note.id : null,
|
id: note ? note.id : null,
|
||||||
@ -338,7 +338,7 @@ class AppGui {
|
|||||||
|
|
||||||
if (consoleWidget.isMaximized__ === doMaximize) return;
|
if (consoleWidget.isMaximized__ === doMaximize) return;
|
||||||
|
|
||||||
let constraints = {
|
const constraints = {
|
||||||
type: 'stretch',
|
type: 'stretch',
|
||||||
factor: !doMaximize ? 1 : 4,
|
factor: !doMaximize ? 1 : 4,
|
||||||
};
|
};
|
||||||
@ -415,10 +415,10 @@ class AppGui {
|
|||||||
async handleModelAction(action) {
|
async handleModelAction(action) {
|
||||||
this.logger().info('Action:', action);
|
this.logger().info('Action:', action);
|
||||||
|
|
||||||
let state = Object.assign({}, defaultState);
|
const state = Object.assign({}, defaultState);
|
||||||
state.notes = this.widget('noteList').items;
|
state.notes = this.widget('noteList').items;
|
||||||
|
|
||||||
let newState = reducer(state, action);
|
const newState = reducer(state, action);
|
||||||
|
|
||||||
if (newState !== state) {
|
if (newState !== state) {
|
||||||
this.widget('noteList').items = newState.notes;
|
this.widget('noteList').items = newState.notes;
|
||||||
@ -485,9 +485,9 @@ class AppGui {
|
|||||||
// this.logger().debug('Got command: ' + cmd);
|
// this.logger().debug('Got command: ' + cmd);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let note = this.widget('noteList').currentItem;
|
const note = this.widget('noteList').currentItem;
|
||||||
let folder = this.widget('folderList').currentItem;
|
const folder = this.widget('folderList').currentItem;
|
||||||
let args = splitCommandString(cmd);
|
const args = splitCommandString(cmd);
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
if (args[i] == '$n') {
|
if (args[i] == '$n') {
|
||||||
@ -548,7 +548,7 @@ class AppGui {
|
|||||||
stdout(text) {
|
stdout(text) {
|
||||||
if (text === null || text === undefined) return;
|
if (text === null || text === undefined) return;
|
||||||
|
|
||||||
let lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i];
|
const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i];
|
||||||
this.widget('console').addLine(v);
|
this.widget('console').addLine(v);
|
||||||
@ -626,7 +626,7 @@ class AppGui {
|
|||||||
|
|
||||||
if (link.type === 'item') {
|
if (link.type === 'item') {
|
||||||
const itemId = link.id;
|
const itemId = link.id;
|
||||||
let item = await BaseItem.loadItemById(itemId);
|
const item = await BaseItem.loadItemById(itemId);
|
||||||
if (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible
|
if (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible
|
||||||
|
|
||||||
if (item.type_ === BaseModel.TYPE_RESOURCE) {
|
if (item.type_ === BaseModel.TYPE_RESOURCE) {
|
||||||
@ -750,7 +750,7 @@ class AppGui {
|
|||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
const shortcutKey = this.currentShortcutKeys_.join('');
|
const shortcutKey = this.currentShortcutKeys_.join('');
|
||||||
let keymapItem = this.keymapItemByKey(shortcutKey);
|
const keymapItem = this.keymapItemByKey(shortcutKey);
|
||||||
|
|
||||||
// If this command is an alias to another command, resolve to the actual command
|
// If this command is an alias to another command, resolve to the actual command
|
||||||
|
|
||||||
@ -766,7 +766,7 @@ class AppGui {
|
|||||||
if (keymapItem.type === 'function') {
|
if (keymapItem.type === 'function') {
|
||||||
this.processFunctionCommand(keymapItem.command);
|
this.processFunctionCommand(keymapItem.command);
|
||||||
} else if (keymapItem.type === 'prompt') {
|
} else if (keymapItem.type === 'prompt') {
|
||||||
let promptOptions = {};
|
const promptOptions = {};
|
||||||
if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition;
|
if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition;
|
||||||
const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions);
|
const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions);
|
||||||
this.addCommandToConsole(commandString);
|
this.addCommandToConsole(commandString);
|
||||||
|
@ -47,7 +47,7 @@ class Application extends BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadItem(type, pattern, options = null) {
|
async loadItem(type, pattern, options = null) {
|
||||||
let output = await this.loadItems(type, pattern, options);
|
const output = await this.loadItems(type, pattern, options);
|
||||||
|
|
||||||
if (output.length > 1) {
|
if (output.length > 1) {
|
||||||
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
|
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
|
||||||
@ -144,7 +144,7 @@ class Application extends BaseApplication {
|
|||||||
if (options.type === 'boolean') {
|
if (options.type === 'boolean') {
|
||||||
if (answer === null) return false; // Pressed ESCAPE
|
if (answer === null) return false; // Pressed ESCAPE
|
||||||
if (!answer) answer = options.answers[0];
|
if (!answer) answer = options.answers[0];
|
||||||
let positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1;
|
const positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1;
|
||||||
return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase();
|
return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase();
|
||||||
} else {
|
} else {
|
||||||
return answer;
|
return answer;
|
||||||
@ -181,7 +181,7 @@ class Application extends BaseApplication {
|
|||||||
const ext = fileExtension(path);
|
const ext = fileExtension(path);
|
||||||
if (ext != 'js') return;
|
if (ext != 'js') return;
|
||||||
|
|
||||||
let CommandClass = require(`./${path}`);
|
const CommandClass = require(`./${path}`);
|
||||||
let cmd = new CommandClass();
|
let cmd = new CommandClass();
|
||||||
if (!cmd.enabled()) return;
|
if (!cmd.enabled()) return;
|
||||||
cmd = this.setupCommand(cmd);
|
cmd = this.setupCommand(cmd);
|
||||||
@ -192,8 +192,8 @@ class Application extends BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uiType !== null) {
|
if (uiType !== null) {
|
||||||
let temp = [];
|
const temp = [];
|
||||||
for (let n in this.commands_) {
|
for (const n in this.commands_) {
|
||||||
if (!this.commands_.hasOwnProperty(n)) continue;
|
if (!this.commands_.hasOwnProperty(n)) continue;
|
||||||
const c = this.commands_[n];
|
const c = this.commands_[n];
|
||||||
if (!c.supportsUi(uiType)) continue;
|
if (!c.supportsUi(uiType)) continue;
|
||||||
@ -207,8 +207,8 @@ class Application extends BaseApplication {
|
|||||||
|
|
||||||
async commandNames() {
|
async commandNames() {
|
||||||
const metadata = await this.commandMetadata();
|
const metadata = await this.commandMetadata();
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let n in metadata) {
|
for (const n in metadata) {
|
||||||
if (!metadata.hasOwnProperty(n)) continue;
|
if (!metadata.hasOwnProperty(n)) continue;
|
||||||
output.push(n);
|
output.push(n);
|
||||||
}
|
}
|
||||||
@ -227,7 +227,7 @@ class Application extends BaseApplication {
|
|||||||
const commands = this.commands();
|
const commands = this.commands();
|
||||||
|
|
||||||
output = {};
|
output = {};
|
||||||
for (let n in commands) {
|
for (const n in commands) {
|
||||||
if (!commands.hasOwnProperty(n)) continue;
|
if (!commands.hasOwnProperty(n)) continue;
|
||||||
const cmd = commands[n];
|
const cmd = commands[n];
|
||||||
output[n] = cmd.metadata();
|
output[n] = cmd.metadata();
|
||||||
@ -251,7 +251,7 @@ class Application extends BaseApplication {
|
|||||||
CommandClass = require(`${__dirname}/command-${name}.js`);
|
CommandClass = require(`${__dirname}/command-${name}.js`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
|
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
|
||||||
let e = new Error(_('No such command: %s', name));
|
const e = new Error(_('No such command: %s', name));
|
||||||
e.type = 'notFound';
|
e.type = 'notFound';
|
||||||
throw e;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
@ -362,7 +362,7 @@ class Application extends BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const output = [];
|
const output = [];
|
||||||
for (let n in itemsByCommand) {
|
for (const n in itemsByCommand) {
|
||||||
if (!itemsByCommand.hasOwnProperty(n)) continue;
|
if (!itemsByCommand.hasOwnProperty(n)) continue;
|
||||||
output.push(itemsByCommand[n]);
|
output.push(itemsByCommand[n]);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
var { app } = require('./app.js');
|
const { app } = require('./app.js');
|
||||||
var Note = require('lib/models/Note.js');
|
const Note = require('lib/models/Note.js');
|
||||||
var Folder = require('lib/models/Folder.js');
|
const Folder = require('lib/models/Folder.js');
|
||||||
var Tag = require('lib/models/Tag.js');
|
const Tag = require('lib/models/Tag.js');
|
||||||
var { cliUtils } = require('./cli-utils.js');
|
const { cliUtils } = require('./cli-utils.js');
|
||||||
var yargParser = require('yargs-parser');
|
const yargParser = require('yargs-parser');
|
||||||
var fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
async function handleAutocompletionPromise(line) {
|
async function handleAutocompletionPromise(line) {
|
||||||
// Auto-complete the command name
|
// Auto-complete the command name
|
||||||
const names = await app().commandNames();
|
const names = await app().commandNames();
|
||||||
let words = getArguments(line);
|
const words = getArguments(line);
|
||||||
// If there is only one word and it is not already a command name then you
|
// If there is only one word and it is not already a command name then you
|
||||||
// should look for commands it could be
|
// should look for commands it could be
|
||||||
if (words.length == 1) {
|
if (words.length == 1) {
|
||||||
if (names.indexOf(words[0]) === -1) {
|
if (names.indexOf(words[0]) === -1) {
|
||||||
let x = names.filter(n => n.indexOf(words[0]) === 0);
|
const x = names.filter(n => n.indexOf(words[0]) === 0);
|
||||||
if (x.length === 1) {
|
if (x.length === 1) {
|
||||||
return `${x[0]} `;
|
return `${x[0]} `;
|
||||||
}
|
}
|
||||||
@ -36,8 +36,8 @@ async function handleAutocompletionPromise(line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// complete an option
|
// complete an option
|
||||||
let next = words.length > 1 ? words[words.length - 1] : '';
|
const next = words.length > 1 ? words[words.length - 1] : '';
|
||||||
let l = [];
|
const l = [];
|
||||||
if (next[0] === '-') {
|
if (next[0] === '-') {
|
||||||
for (let i = 0; i < metadata.options.length; i++) {
|
for (let i = 0; i < metadata.options.length; i++) {
|
||||||
const options = metadata.options[i][0].split(' ');
|
const options = metadata.options[i][0].split(' ');
|
||||||
@ -60,7 +60,7 @@ async function handleAutocompletionPromise(line) {
|
|||||||
if (l.length === 0) {
|
if (l.length === 0) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
let ret = l.map(a => toCommandLine(a));
|
const ret = l.map(a => toCommandLine(a));
|
||||||
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ async function handleAutocompletionPromise(line) {
|
|||||||
// words that don't start with a - less one for the command name
|
// words that don't start with a - less one for the command name
|
||||||
const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1;
|
const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1;
|
||||||
|
|
||||||
let cmdUsage = yargParser(metadata.usage)['_'];
|
const cmdUsage = yargParser(metadata.usage)['_'];
|
||||||
cmdUsage.splice(0, 1);
|
cmdUsage.splice(0, 1);
|
||||||
|
|
||||||
if (cmdUsage.length >= positionalArgs) {
|
if (cmdUsage.length >= positionalArgs) {
|
||||||
@ -95,29 +95,29 @@ async function handleAutocompletionPromise(line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argName == 'tag') {
|
if (argName == 'tag') {
|
||||||
let tags = await Tag.search({ titlePattern: `${next}*` });
|
const tags = await Tag.search({ titlePattern: `${next}*` });
|
||||||
l.push(...tags.map(n => n.title));
|
l.push(...tags.map(n => n.title));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argName == 'file') {
|
if (argName == 'file') {
|
||||||
let files = await fs.readdir('.');
|
const files = await fs.readdir('.');
|
||||||
l.push(...files);
|
l.push(...files);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argName == 'tag-command') {
|
if (argName == 'tag-command') {
|
||||||
let c = filterList(['add', 'remove', 'list', 'notetags'], next);
|
const c = filterList(['add', 'remove', 'list', 'notetags'], next);
|
||||||
l.push(...c);
|
l.push(...c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argName == 'todo-command') {
|
if (argName == 'todo-command') {
|
||||||
let c = filterList(['toggle', 'clear'], next);
|
const c = filterList(['toggle', 'clear'], next);
|
||||||
l.push(...c);
|
l.push(...c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (l.length === 1) {
|
if (l.length === 1) {
|
||||||
return toCommandLine([...words.slice(0, -1), l[0]]);
|
return toCommandLine([...words.slice(0, -1), l[0]]);
|
||||||
} else if (l.length > 1) {
|
} else if (l.length > 1) {
|
||||||
let ret = l.map(a => toCommandLine(a));
|
const ret = l.map(a => toCommandLine(a));
|
||||||
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ function getArguments(line) {
|
|||||||
let inSingleQuotes = false;
|
let inSingleQuotes = false;
|
||||||
let inDoubleQuotes = false;
|
let inDoubleQuotes = false;
|
||||||
let currentWord = '';
|
let currentWord = '';
|
||||||
let parsed = [];
|
const parsed = [];
|
||||||
for (let i = 0; i < line.length; i++) {
|
for (let i = 0; i < line.length; i++) {
|
||||||
if (line[i] === '"') {
|
if (line[i] === '"') {
|
||||||
if (inDoubleQuotes) {
|
if (inDoubleQuotes) {
|
||||||
@ -192,7 +192,7 @@ function getArguments(line) {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
function filterList(list, next) {
|
function filterList(list, next) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
if (list[i].indexOf(next) !== 0) continue;
|
if (list[i].indexOf(next) !== 0) continue;
|
||||||
output.push(list[i]);
|
output.push(list[i]);
|
||||||
|
@ -50,7 +50,7 @@ class BaseCommand {
|
|||||||
async cancel() {}
|
async cancel() {}
|
||||||
|
|
||||||
name() {
|
name() {
|
||||||
let r = this.usage().split(' ');
|
const r = this.usage().split(' ');
|
||||||
return r[0];
|
return r[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ function wrap(text, indent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderOptions(options) {
|
function renderOptions(options) {
|
||||||
let output = [];
|
const output = [];
|
||||||
const optionColWidth = getOptionColWidth(options);
|
const optionColWidth = getOptionColWidth(options);
|
||||||
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
for (let i = 0; i < options.length; i++) {
|
||||||
let option = options[i];
|
const option = options[i];
|
||||||
const flag = option[0];
|
const flag = option[0];
|
||||||
const indent = INDENT + INDENT + ' '.repeat(optionColWidth + 2);
|
const indent = INDENT + INDENT + ' '.repeat(optionColWidth + 2);
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ function renderOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderCommand(cmd) {
|
function renderCommand(cmd) {
|
||||||
let output = [];
|
const output = [];
|
||||||
output.push(INDENT + cmd.usage());
|
output.push(INDENT + cmd.usage());
|
||||||
output.push('');
|
output.push('');
|
||||||
output.push(wrap(cmd.description(), INDENT + INDENT));
|
output.push(wrap(cmd.description(), INDENT + INDENT));
|
||||||
@ -48,14 +48,14 @@ function renderCommand(cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCommands() {
|
function getCommands() {
|
||||||
let output = [];
|
const output = [];
|
||||||
fs.readdirSync(__dirname).forEach(path => {
|
fs.readdirSync(__dirname).forEach(path => {
|
||||||
if (path.indexOf('command-') !== 0) return;
|
if (path.indexOf('command-') !== 0) return;
|
||||||
const ext = fileExtension(path);
|
const ext = fileExtension(path);
|
||||||
if (ext != 'js') return;
|
if (ext != 'js') return;
|
||||||
|
|
||||||
let CommandClass = require(`./${path}`);
|
const CommandClass = require(`./${path}`);
|
||||||
let cmd = new CommandClass();
|
const cmd = new CommandClass();
|
||||||
if (!cmd.enabled()) return;
|
if (!cmd.enabled()) return;
|
||||||
if (cmd.hidden()) return;
|
if (cmd.hidden()) return;
|
||||||
output.push(cmd);
|
output.push(cmd);
|
||||||
@ -73,7 +73,7 @@ function getOptionColWidth(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getHeader() {
|
function getHeader() {
|
||||||
let output = [];
|
const output = [];
|
||||||
|
|
||||||
output.push('NAME');
|
output.push('NAME');
|
||||||
output.push('');
|
output.push('');
|
||||||
@ -84,7 +84,7 @@ function getHeader() {
|
|||||||
output.push('DESCRIPTION');
|
output.push('DESCRIPTION');
|
||||||
output.push('');
|
output.push('');
|
||||||
|
|
||||||
let description = [];
|
const description = [];
|
||||||
description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.');
|
description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.');
|
||||||
description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.');
|
description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.');
|
||||||
description.push('\n\n');
|
description.push('\n\n');
|
||||||
@ -98,7 +98,7 @@ function getHeader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getFooter() {
|
function getFooter() {
|
||||||
let output = [];
|
const output = [];
|
||||||
|
|
||||||
output.push('WEBSITE');
|
output.push('WEBSITE');
|
||||||
output.push('');
|
output.push('');
|
||||||
@ -120,10 +120,10 @@ async function main() {
|
|||||||
// setLocale('fr_FR');
|
// setLocale('fr_FR');
|
||||||
|
|
||||||
const commands = getCommands();
|
const commands = getCommands();
|
||||||
let commandBlocks = [];
|
const commandBlocks = [];
|
||||||
|
|
||||||
for (let i = 0; i < commands.length; i++) {
|
for (let i = 0; i < commands.length; i++) {
|
||||||
let cmd = commands[i];
|
const cmd = commands[i];
|
||||||
commandBlocks.push(renderCommand(cmd));
|
commandBlocks.push(renderCommand(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ function createClient(id) {
|
|||||||
const client = createClient(1);
|
const client = createClient(1);
|
||||||
|
|
||||||
function execCommand(client, command) {
|
function execCommand(client, command) {
|
||||||
let exePath = `node ${joplinAppPath}`;
|
const exePath = `node ${joplinAppPath}`;
|
||||||
let cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
const cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
||||||
logger.info(`${client.id}: ${command}`);
|
logger.info(`${client.id}: ${command}`);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -129,8 +129,8 @@ testUnits.testCat = async () => {
|
|||||||
await execCommand(client, 'mkbook nb1');
|
await execCommand(client, 'mkbook nb1');
|
||||||
await execCommand(client, 'mknote mynote');
|
await execCommand(client, 'mknote mynote');
|
||||||
|
|
||||||
let folder = await Folder.loadByTitle('nb1');
|
const folder = await Folder.loadByTitle('nb1');
|
||||||
let note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote');
|
const note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote');
|
||||||
|
|
||||||
let r = await execCommand(client, 'cat mynote');
|
let r = await execCommand(client, 'cat mynote');
|
||||||
assertTrue(r.indexOf('mynote') >= 0);
|
assertTrue(r.indexOf('mynote') >= 0);
|
||||||
@ -149,7 +149,7 @@ testUnits.testConfig = async () => {
|
|||||||
await Setting.load();
|
await Setting.load();
|
||||||
assertEquals('subl', Setting.value('editor'));
|
assertEquals('subl', Setting.value('editor'));
|
||||||
|
|
||||||
let r = await execCommand(client, 'config');
|
const r = await execCommand(client, 'config');
|
||||||
assertTrue(r.indexOf('editor') >= 0);
|
assertTrue(r.indexOf('editor') >= 0);
|
||||||
assertTrue(r.indexOf('subl') >= 0);
|
assertTrue(r.indexOf('subl') >= 0);
|
||||||
};
|
};
|
||||||
@ -161,14 +161,14 @@ testUnits.testCp = async () => {
|
|||||||
|
|
||||||
await execCommand(client, 'cp n1');
|
await execCommand(client, 'cp n1');
|
||||||
|
|
||||||
let f1 = await Folder.loadByTitle('nb1');
|
const f1 = await Folder.loadByTitle('nb1');
|
||||||
let f2 = await Folder.loadByTitle('nb2');
|
const f2 = await Folder.loadByTitle('nb2');
|
||||||
let notes = await Note.previews(f1.id);
|
let notes = await Note.previews(f1.id);
|
||||||
|
|
||||||
assertEquals(2, notes.length);
|
assertEquals(2, notes.length);
|
||||||
|
|
||||||
await execCommand(client, 'cp n1 nb2');
|
await execCommand(client, 'cp n1 nb2');
|
||||||
let notesF1 = await Note.previews(f1.id);
|
const notesF1 = await Note.previews(f1.id);
|
||||||
assertEquals(2, notesF1.length);
|
assertEquals(2, notesF1.length);
|
||||||
notes = await Note.previews(f2.id);
|
notes = await Note.previews(f2.id);
|
||||||
assertEquals(1, notes.length);
|
assertEquals(1, notes.length);
|
||||||
@ -179,7 +179,7 @@ testUnits.testLs = async () => {
|
|||||||
await execCommand(client, 'mkbook nb1');
|
await execCommand(client, 'mkbook nb1');
|
||||||
await execCommand(client, 'mknote note1');
|
await execCommand(client, 'mknote note1');
|
||||||
await execCommand(client, 'mknote note2');
|
await execCommand(client, 'mknote note2');
|
||||||
let r = await execCommand(client, 'ls');
|
const r = await execCommand(client, 'ls');
|
||||||
|
|
||||||
assertTrue(r.indexOf('note1') >= 0);
|
assertTrue(r.indexOf('note1') >= 0);
|
||||||
assertTrue(r.indexOf('note2') >= 0);
|
assertTrue(r.indexOf('note2') >= 0);
|
||||||
@ -191,8 +191,8 @@ testUnits.testMv = async () => {
|
|||||||
await execCommand(client, 'mknote n1');
|
await execCommand(client, 'mknote n1');
|
||||||
await execCommand(client, 'mv n1 nb2');
|
await execCommand(client, 'mv n1 nb2');
|
||||||
|
|
||||||
let f1 = await Folder.loadByTitle('nb1');
|
const f1 = await Folder.loadByTitle('nb1');
|
||||||
let f2 = await Folder.loadByTitle('nb2');
|
const f2 = await Folder.loadByTitle('nb2');
|
||||||
let notes1 = await Note.previews(f1.id);
|
let notes1 = await Note.previews(f1.id);
|
||||||
let notes2 = await Note.previews(f2.id);
|
let notes2 = await Note.previews(f2.id);
|
||||||
|
|
||||||
@ -224,12 +224,12 @@ async function main() {
|
|||||||
let onlyThisTest = 'testMv';
|
let onlyThisTest = 'testMv';
|
||||||
onlyThisTest = '';
|
onlyThisTest = '';
|
||||||
|
|
||||||
for (let n in testUnits) {
|
for (const n in testUnits) {
|
||||||
if (!testUnits.hasOwnProperty(n)) continue;
|
if (!testUnits.hasOwnProperty(n)) continue;
|
||||||
if (onlyThisTest && n != onlyThisTest) continue;
|
if (onlyThisTest && n != onlyThisTest) continue;
|
||||||
|
|
||||||
await clearDatabase();
|
await clearDatabase();
|
||||||
let testName = n.substr(4).toLowerCase();
|
const testName = n.substr(4).toLowerCase();
|
||||||
process.stdout.write(`${testName}: `);
|
process.stdout.write(`${testName}: `);
|
||||||
await testUnits[n]();
|
await testUnits[n]();
|
||||||
console.info('');
|
console.info('');
|
||||||
|
@ -11,27 +11,27 @@ cliUtils.printArray = function(logFunction, rows) {
|
|||||||
const ALIGN_LEFT = 0;
|
const ALIGN_LEFT = 0;
|
||||||
const ALIGN_RIGHT = 1;
|
const ALIGN_RIGHT = 1;
|
||||||
|
|
||||||
let colWidths = [];
|
const colWidths = [];
|
||||||
let colAligns = [];
|
const colAligns = [];
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
let row = rows[i];
|
const row = rows[i];
|
||||||
|
|
||||||
for (let j = 0; j < row.length; j++) {
|
for (let j = 0; j < row.length; j++) {
|
||||||
let item = row[j];
|
const item = row[j];
|
||||||
let width = item ? item.toString().length : 0;
|
const width = item ? item.toString().length : 0;
|
||||||
let align = typeof item == 'number' ? ALIGN_RIGHT : ALIGN_LEFT;
|
const align = typeof item == 'number' ? ALIGN_RIGHT : ALIGN_LEFT;
|
||||||
if (!colWidths[j] || colWidths[j] < width) colWidths[j] = width;
|
if (!colWidths[j] || colWidths[j] < width) colWidths[j] = width;
|
||||||
if (colAligns.length <= j) colAligns[j] = align;
|
if (colAligns.length <= j) colAligns[j] = align;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let row = 0; row < rows.length; row++) {
|
for (let row = 0; row < rows.length; row++) {
|
||||||
let line = [];
|
const line = [];
|
||||||
for (let col = 0; col < colWidths.length; col++) {
|
for (let col = 0; col < colWidths.length; col++) {
|
||||||
let item = rows[row][col];
|
const item = rows[row][col];
|
||||||
let width = colWidths[col];
|
const width = colWidths[col];
|
||||||
let dir = colAligns[col] == ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT;
|
const dir = colAligns[col] == ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT;
|
||||||
line.push(stringPadding(item, width, ' ', dir));
|
line.push(stringPadding(item, width, ' ', dir));
|
||||||
}
|
}
|
||||||
logFunction(line.join(' '));
|
logFunction(line.join(' '));
|
||||||
@ -39,7 +39,7 @@ cliUtils.printArray = function(logFunction, rows) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
cliUtils.parseFlags = function(flags) {
|
cliUtils.parseFlags = function(flags) {
|
||||||
let output = {};
|
const output = {};
|
||||||
flags = flags.split(',');
|
flags = flags.split(',');
|
||||||
for (let i = 0; i < flags.length; i++) {
|
for (let i = 0; i < flags.length; i++) {
|
||||||
let f = flags[i].trim();
|
let f = flags[i].trim();
|
||||||
@ -76,11 +76,11 @@ cliUtils.parseCommandArg = function(arg) {
|
|||||||
cliUtils.makeCommandArgs = function(cmd, argv) {
|
cliUtils.makeCommandArgs = function(cmd, argv) {
|
||||||
let cmdUsage = cmd.usage();
|
let cmdUsage = cmd.usage();
|
||||||
cmdUsage = yargParser(cmdUsage);
|
cmdUsage = yargParser(cmdUsage);
|
||||||
let output = {};
|
const output = {};
|
||||||
|
|
||||||
let options = cmd.options();
|
const options = cmd.options();
|
||||||
let booleanFlags = [];
|
const booleanFlags = [];
|
||||||
let aliases = {};
|
const aliases = {};
|
||||||
for (let i = 0; i < options.length; i++) {
|
for (let i = 0; i < options.length; i++) {
|
||||||
if (options[i].length != 2) throw new Error(`Invalid options: ${options[i]}`);
|
if (options[i].length != 2) throw new Error(`Invalid options: ${options[i]}`);
|
||||||
let flags = options[i][0];
|
let flags = options[i][0];
|
||||||
@ -97,7 +97,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = yargParser(argv, {
|
const args = yargParser(argv, {
|
||||||
boolean: booleanFlags,
|
boolean: booleanFlags,
|
||||||
alias: aliases,
|
alias: aliases,
|
||||||
string: ['_'],
|
string: ['_'],
|
||||||
@ -113,8 +113,8 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let argOptions = {};
|
const argOptions = {};
|
||||||
for (let key in args) {
|
for (const key in args) {
|
||||||
if (!args.hasOwnProperty(key)) continue;
|
if (!args.hasOwnProperty(key)) continue;
|
||||||
if (key == '_') continue;
|
if (key == '_') continue;
|
||||||
argOptions[key] = args[key];
|
argOptions[key] = args[key];
|
||||||
@ -134,7 +134,7 @@ cliUtils.promptMcq = function(message, answers) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
message += '\n\n';
|
message += '\n\n';
|
||||||
for (let n in answers) {
|
for (const n in answers) {
|
||||||
if (!answers.hasOwnProperty(n)) continue;
|
if (!answers.hasOwnProperty(n)) continue;
|
||||||
message += `${_('%s: %s', n, answers[n])}\n`;
|
message += `${_('%s: %s', n, answers[n])}\n`;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let title = args['note'];
|
const title = args['note'];
|
||||||
|
|
||||||
let note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
const note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||||
this.encryptionCheck(note);
|
this.encryptionCheck(note);
|
||||||
if (!note) throw new Error(_('Cannot find "%s".', title));
|
if (!note) throw new Error(_('Cannot find "%s".', title));
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let title = args['note'];
|
const title = args['note'];
|
||||||
|
|
||||||
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||||
if (!item) throw new Error(_('Cannot find "%s".', title));
|
if (!item) throw new Error(_('Cannot find "%s".', title));
|
||||||
|
|
||||||
const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item);
|
const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item);
|
||||||
|
@ -35,7 +35,7 @@ class Command extends BaseCommand {
|
|||||||
});
|
});
|
||||||
|
|
||||||
inputStream.on('end', () => {
|
inputStream.on('end', () => {
|
||||||
let json = chunks.join('');
|
const json = chunks.join('');
|
||||||
let settingsObj;
|
let settingsObj;
|
||||||
try {
|
try {
|
||||||
settingsObj = JSON.parse(json);
|
settingsObj = JSON.parse(json);
|
||||||
@ -83,7 +83,7 @@ class Command extends BaseCommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isExport || (!isImport && !args.value)) {
|
if (isExport || (!isImport && !args.value)) {
|
||||||
let keys = Setting.keys(!verbose, 'cli');
|
const keys = Setting.keys(!verbose, 'cli');
|
||||||
keys.sort();
|
keys.sort();
|
||||||
|
|
||||||
if (isExport) {
|
if (isExport) {
|
||||||
|
@ -18,15 +18,15 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
async action() {
|
async action() {
|
||||||
let items = [];
|
let items = [];
|
||||||
let folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
for (let i = 0; i < folders.length; i++) {
|
for (let i = 0; i < folders.length; i++) {
|
||||||
let folder = folders[i];
|
const folder = folders[i];
|
||||||
let notes = await Note.previews(folder.id);
|
const notes = await Note.previews(folder.id);
|
||||||
items.push(folder);
|
items.push(folder);
|
||||||
items = items.concat(notes);
|
items = items.concat(notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tags = await Tag.all();
|
const tags = await Tag.all();
|
||||||
for (let i = 0; i < tags.length; i++) {
|
for (let i = 0; i < tags.length; i++) {
|
||||||
tags[i].notes_ = await Tag.noteIds(tags[i].id);
|
tags[i].notes_ = await Tag.noteIds(tags[i].id);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ class Command extends BaseCommand {
|
|||||||
if (!targetPath) throw new Error('Please specify the sync target path.');
|
if (!targetPath) throw new Error('Please specify the sync target path.');
|
||||||
|
|
||||||
const dirPaths = function(targetPath) {
|
const dirPaths = function(targetPath) {
|
||||||
let paths = [];
|
const paths = [];
|
||||||
fs.readdirSync(targetPath).forEach(path => {
|
fs.readdirSync(targetPath).forEach(path => {
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
});
|
});
|
||||||
@ -151,10 +151,10 @@ class Command extends BaseCommand {
|
|||||||
let encryptedResourceCount = 0;
|
let encryptedResourceCount = 0;
|
||||||
let otherItemCount = 0;
|
let otherItemCount = 0;
|
||||||
|
|
||||||
let encryptedPaths = [];
|
const encryptedPaths = [];
|
||||||
let decryptedPaths = [];
|
const decryptedPaths = [];
|
||||||
|
|
||||||
let paths = dirPaths(targetPath);
|
const paths = dirPaths(targetPath);
|
||||||
|
|
||||||
for (let i = 0; i < paths.length; i++) {
|
for (let i = 0; i < paths.length; i++) {
|
||||||
const path = paths[i];
|
const path = paths[i];
|
||||||
@ -164,7 +164,7 @@ class Command extends BaseCommand {
|
|||||||
// this.stdout(fullPath);
|
// this.stdout(fullPath);
|
||||||
|
|
||||||
if (path === '.resource') {
|
if (path === '.resource') {
|
||||||
let resourcePaths = dirPaths(fullPath);
|
const resourcePaths = dirPaths(fullPath);
|
||||||
for (let j = 0; j < resourcePaths.length; j++) {
|
for (let j = 0; j < resourcePaths.length; j++) {
|
||||||
const resourcePath = resourcePaths[j];
|
const resourcePath = resourcePaths[j];
|
||||||
resourceCount++;
|
resourceCount++;
|
||||||
|
@ -35,7 +35,7 @@ class Command extends BaseCommand {
|
|||||||
// Load note or create it if it doesn't exist
|
// Load note or create it if it doesn't exist
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
let title = args['note'];
|
const title = args['note'];
|
||||||
|
|
||||||
if (!app().currentFolder()) throw new Error(_('No active notebook.'));
|
if (!app().currentFolder()) throw new Error(_('No active notebook.'));
|
||||||
let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
|
let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
|
||||||
@ -91,7 +91,7 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
const updatedContent = await fs.readFile(tempFilePath, 'utf8');
|
const updatedContent = await fs.readFile(tempFilePath, 'utf8');
|
||||||
if (updatedContent !== originalContent) {
|
if (updatedContent !== originalContent) {
|
||||||
let updatedNote = await Note.unserializeForEdit(updatedContent);
|
const updatedNote = await Note.unserializeForEdit(updatedContent);
|
||||||
updatedNote.id = note.id;
|
updatedNote.id = note.id;
|
||||||
await Note.save(updatedNote);
|
await Note.save(updatedNote);
|
||||||
this.stdout(_('Note has been saved.'));
|
this.stdout(_('Note has been saved.'));
|
||||||
|
@ -24,7 +24,7 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let exportOptions = {};
|
const exportOptions = {};
|
||||||
exportOptions.path = args.path;
|
exportOptions.path = args.path;
|
||||||
|
|
||||||
exportOptions.format = args.options.format ? args.options.format : 'jex';
|
exportOptions.format = args.options.format ? args.options.format : 'jex';
|
||||||
|
@ -14,9 +14,9 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let title = args['note'];
|
const title = args['note'];
|
||||||
|
|
||||||
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||||
if (!item) throw new Error(_('Cannot find "%s".', title));
|
if (!item) throw new Error(_('Cannot find "%s".', title));
|
||||||
const url = Note.geolocationUrl(item);
|
const url = Note.geolocationUrl(item);
|
||||||
this.stdout(url);
|
this.stdout(url);
|
||||||
|
@ -15,8 +15,8 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
allCommands() {
|
allCommands() {
|
||||||
const commands = app().commands(app().uiType());
|
const commands = app().commands(app().uiType());
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let n in commands) {
|
for (const n in commands) {
|
||||||
if (!commands.hasOwnProperty(n)) continue;
|
if (!commands.hasOwnProperty(n)) continue;
|
||||||
const command = commands[n];
|
const command = commands[n];
|
||||||
if (command.hidden()) continue;
|
if (command.hidden()) continue;
|
||||||
@ -48,7 +48,7 @@ class Command extends BaseCommand {
|
|||||||
.gui()
|
.gui()
|
||||||
.keymap();
|
.keymap();
|
||||||
|
|
||||||
let rows = [];
|
const rows = [];
|
||||||
|
|
||||||
for (let i = 0; i < keymap.length; i++) {
|
for (let i = 0; i < keymap.length; i++) {
|
||||||
const item = keymap[i];
|
const item = keymap[i];
|
||||||
|
@ -25,7 +25,7 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
|
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
|
||||||
|
|
||||||
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
|
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class Command extends BaseCommand {
|
|||||||
// onProgress/onError supported by Enex import only
|
// onProgress/onError supported by Enex import only
|
||||||
|
|
||||||
importOptions.onProgress = progressState => {
|
importOptions.onProgress = progressState => {
|
||||||
let line = [];
|
const line = [];
|
||||||
line.push(_('Found: %d.', progressState.loaded));
|
line.push(_('Found: %d.', progressState.loaded));
|
||||||
line.push(_('Created: %d.', progressState.created));
|
line.push(_('Created: %d.', progressState.created));
|
||||||
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
||||||
@ -51,7 +51,7 @@ class Command extends BaseCommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
importOptions.onError = error => {
|
importOptions.onError = error => {
|
||||||
let s = error.trace ? error.trace : error.toString();
|
const s = error.trace ? error.trace : error.toString();
|
||||||
this.stdout(s);
|
this.stdout(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let pattern = args['note-pattern'];
|
const pattern = args['note-pattern'];
|
||||||
let items = [];
|
let items = [];
|
||||||
let options = args.options;
|
const options = args.options;
|
||||||
|
|
||||||
let queryOptions = {};
|
const queryOptions = {};
|
||||||
if (options.limit) queryOptions.limit = options.limit;
|
if (options.limit) queryOptions.limit = options.limit;
|
||||||
if (options.sort) {
|
if (options.sort) {
|
||||||
queryOptions.orderBy = options.sort;
|
queryOptions.orderBy = options.sort;
|
||||||
@ -70,19 +70,19 @@ class Command extends BaseCommand {
|
|||||||
} else {
|
} else {
|
||||||
let hasTodos = false;
|
let hasTodos = false;
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
let item = items[i];
|
const item = items[i];
|
||||||
if (item.is_todo) {
|
if (item.is_todo) {
|
||||||
hasTodos = true;
|
hasTodos = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let seenTitles = [];
|
const seenTitles = [];
|
||||||
let rows = [];
|
const rows = [];
|
||||||
let shortIdShown = false;
|
let shortIdShown = false;
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
let item = items[i];
|
const item = items[i];
|
||||||
let row = [];
|
const row = [];
|
||||||
|
|
||||||
if (options.long) {
|
if (options.long) {
|
||||||
row.push(BaseModel.shortId(item.id));
|
row.push(BaseModel.shortId(item.id));
|
||||||
|
@ -13,7 +13,7 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
|
const folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
|
||||||
app().switchCurrentFolder(folder);
|
app().switchCurrentFolder(folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' });
|
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' });
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
let ids = notes.map(n => n.id);
|
const ids = notes.map(n => n.id);
|
||||||
await Note.batchDelete(ids);
|
await Note.batchDelete(ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let pattern = args['pattern'];
|
const pattern = args['pattern'];
|
||||||
let folderTitle = args['notebook'];
|
const folderTitle = args['notebook'];
|
||||||
|
|
||||||
let folder = null;
|
let folder = null;
|
||||||
if (folderTitle) {
|
if (folderTitle) {
|
||||||
|
@ -23,18 +23,18 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let title = args['note'];
|
const title = args['note'];
|
||||||
let propName = args['name'];
|
const propName = args['name'];
|
||||||
let propValue = args['value'];
|
let propValue = args['value'];
|
||||||
if (!propValue) propValue = '';
|
if (!propValue) propValue = '';
|
||||||
|
|
||||||
let notes = await app().loadItems(BaseModel.TYPE_NOTE, title);
|
const notes = await app().loadItems(BaseModel.TYPE_NOTE, title);
|
||||||
if (!notes.length) throw new Error(_('Cannot find "%s".', title));
|
if (!notes.length) throw new Error(_('Cannot find "%s".', title));
|
||||||
|
|
||||||
for (let i = 0; i < notes.length; i++) {
|
for (let i = 0; i < notes.length; i++) {
|
||||||
this.encryptionCheck(notes[i]);
|
this.encryptionCheck(notes[i]);
|
||||||
|
|
||||||
let newNote = {
|
const newNote = {
|
||||||
id: notes[i].id,
|
id: notes[i].id,
|
||||||
type_: notes[i].type_,
|
type_: notes[i].type_,
|
||||||
};
|
};
|
||||||
|
@ -14,20 +14,20 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action() {
|
async action() {
|
||||||
let service = new ReportService();
|
const service = new ReportService();
|
||||||
let report = await service.status(Setting.value('sync.target'));
|
const report = await service.status(Setting.value('sync.target'));
|
||||||
|
|
||||||
for (let i = 0; i < report.length; i++) {
|
for (let i = 0; i < report.length; i++) {
|
||||||
let section = report[i];
|
const section = report[i];
|
||||||
|
|
||||||
if (i > 0) this.stdout('');
|
if (i > 0) this.stdout('');
|
||||||
|
|
||||||
this.stdout(`# ${section.title}`);
|
this.stdout(`# ${section.title}`);
|
||||||
this.stdout('');
|
this.stdout('');
|
||||||
|
|
||||||
for (let n in section.body) {
|
for (const n in section.body) {
|
||||||
if (!section.body.hasOwnProperty(n)) continue;
|
if (!section.body.hasOwnProperty(n)) continue;
|
||||||
let line = section.body[n];
|
const line = section.body[n];
|
||||||
this.stdout(line);
|
this.stdout(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,9 +161,9 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
const sync = await syncTarget.synchronizer();
|
const sync = await syncTarget.synchronizer();
|
||||||
|
|
||||||
let options = {
|
const options = {
|
||||||
onProgress: report => {
|
onProgress: report => {
|
||||||
let lines = Synchronizer.reportToLines(report);
|
const lines = Synchronizer.reportToLines(report);
|
||||||
if (lines.length) cliUtils.redraw(lines.join(' '));
|
if (lines.length) cliUtils.redraw(lines.join(' '));
|
||||||
},
|
},
|
||||||
onMessage: msg => {
|
onMessage: msg => {
|
||||||
@ -185,7 +185,7 @@ class Command extends BaseCommand {
|
|||||||
options.context = context;
|
options.context = context;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let newContext = await sync.start(options);
|
const newContext = await sync.start(options);
|
||||||
Setting.setValue(contextKey, JSON.stringify(newContext));
|
Setting.setValue(contextKey, JSON.stringify(newContext));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code == 'alreadyStarted') {
|
if (error.code == 'alreadyStarted') {
|
||||||
|
@ -20,7 +20,7 @@ class Command extends BaseCommand {
|
|||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let tag = null;
|
let tag = null;
|
||||||
let options = args.options;
|
const options = args.options;
|
||||||
|
|
||||||
if (args.tag) tag = await app().loadItem(BaseModel.TYPE_TAG, args.tag);
|
if (args.tag) tag = await app().loadItem(BaseModel.TYPE_TAG, args.tag);
|
||||||
let notes = [];
|
let notes = [];
|
||||||
@ -46,7 +46,7 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
} else if (command == 'list') {
|
} else if (command == 'list') {
|
||||||
if (tag) {
|
if (tag) {
|
||||||
let notes = await Tag.notes(tag.id);
|
const notes = await Tag.notes(tag.id);
|
||||||
notes.map(note => {
|
notes.map(note => {
|
||||||
let line = '';
|
let line = '';
|
||||||
if (options.long) {
|
if (options.long) {
|
||||||
@ -70,7 +70,7 @@ class Command extends BaseCommand {
|
|||||||
this.stdout(line);
|
this.stdout(line);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let tags = await Tag.all();
|
const tags = await Tag.all();
|
||||||
tags.map(tag => {
|
tags.map(tag => {
|
||||||
this.stdout(tag.title);
|
this.stdout(tag.title);
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ class Command extends BaseCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async action(args) {
|
async action(args) {
|
||||||
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
|
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
|
||||||
if (!folder) throw new Error(_('Cannot find "%s".', args['notebook']));
|
if (!folder) throw new Error(_('Cannot find "%s".', args['notebook']));
|
||||||
app().switchCurrentFolder(folder);
|
app().switchCurrentFolder(folder);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ const fs = require('fs-extra');
|
|||||||
const baseDir = `${dirname(__dirname)}/tests/fuzzing`;
|
const baseDir = `${dirname(__dirname)}/tests/fuzzing`;
|
||||||
const syncDir = `${baseDir}/sync`;
|
const syncDir = `${baseDir}/sync`;
|
||||||
const joplinAppPath = `${__dirname}/main.js`;
|
const joplinAppPath = `${__dirname}/main.js`;
|
||||||
let syncDurations = [];
|
const syncDurations = [];
|
||||||
|
|
||||||
const fsDriver = new FsDriverNode();
|
const fsDriver = new FsDriverNode();
|
||||||
Logger.fsDriver_ = fsDriver;
|
Logger.fsDriver_ = fsDriver;
|
||||||
@ -34,10 +34,10 @@ function createClient(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createClients() {
|
async function createClients() {
|
||||||
let output = [];
|
const output = [];
|
||||||
let promises = [];
|
const promises = [];
|
||||||
for (let clientId = 0; clientId < 2; clientId++) {
|
for (let clientId = 0; clientId < 2; clientId++) {
|
||||||
let client = createClient(clientId);
|
const client = createClient(clientId);
|
||||||
promises.push(fs.remove(client.profileDir));
|
promises.push(fs.remove(client.profileDir));
|
||||||
promises.push(
|
promises.push(
|
||||||
execCommand(client, 'config sync.target 2').then(() => {
|
execCommand(client, 'config sync.target 2').then(() => {
|
||||||
@ -2064,8 +2064,8 @@ function randomWord() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function execCommand(client, command, options = {}) {
|
function execCommand(client, command, options = {}) {
|
||||||
let exePath = `node ${joplinAppPath}`;
|
const exePath = `node ${joplinAppPath}`;
|
||||||
let cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`;
|
const cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`;
|
||||||
logger.info(`${client.id}: ${command}`);
|
logger.info(`${client.id}: ${command}`);
|
||||||
|
|
||||||
if (options.killAfter) {
|
if (options.killAfter) {
|
||||||
@ -2073,7 +2073,7 @@ function execCommand(client, command, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let childProcess = exec(cmd, (error, stdout, stderr) => {
|
const childProcess = exec(cmd, (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.signal == 'SIGTERM') {
|
if (error.signal == 'SIGTERM') {
|
||||||
resolve('Process was killed');
|
resolve('Process was killed');
|
||||||
@ -2096,7 +2096,7 @@ function execCommand(client, command, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function clientItems(client) {
|
async function clientItems(client) {
|
||||||
let itemsJson = await execCommand(client, 'dump');
|
const itemsJson = await execCommand(client, 'dump');
|
||||||
try {
|
try {
|
||||||
return JSON.parse(itemsJson);
|
return JSON.parse(itemsJson);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -2105,7 +2105,7 @@ async function clientItems(client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomTag(items) {
|
function randomTag(items) {
|
||||||
let tags = [];
|
const tags = [];
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
if (items[i].type_ != 5) continue;
|
if (items[i].type_ != 5) continue;
|
||||||
tags.push(items[i]);
|
tags.push(items[i]);
|
||||||
@ -2115,7 +2115,7 @@ function randomTag(items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomNote(items) {
|
function randomNote(items) {
|
||||||
let notes = [];
|
const notes = [];
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
if (items[i].type_ != 1) continue;
|
if (items[i].type_ != 1) continue;
|
||||||
notes.push(items[i]);
|
notes.push(items[i]);
|
||||||
@ -2125,14 +2125,14 @@ function randomNote(items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function execRandomCommand(client) {
|
async function execRandomCommand(client) {
|
||||||
let possibleCommands = [
|
const possibleCommands = [
|
||||||
['mkbook {word}', 40], // CREATE FOLDER
|
['mkbook {word}', 40], // CREATE FOLDER
|
||||||
['mknote {word}', 70], // CREATE NOTE
|
['mknote {word}', 70], // CREATE NOTE
|
||||||
[
|
[
|
||||||
async () => {
|
async () => {
|
||||||
// DELETE RANDOM ITEM
|
// DELETE RANDOM ITEM
|
||||||
let items = await clientItems(client);
|
const items = await clientItems(client);
|
||||||
let item = randomElement(items);
|
const item = randomElement(items);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
if (item.type_ == 1) {
|
if (item.type_ == 1) {
|
||||||
@ -2150,8 +2150,8 @@ async function execRandomCommand(client) {
|
|||||||
[
|
[
|
||||||
async () => {
|
async () => {
|
||||||
// SYNC
|
// SYNC
|
||||||
let avgSyncDuration = averageSyncDuration();
|
const avgSyncDuration = averageSyncDuration();
|
||||||
let options = {};
|
const options = {};
|
||||||
if (!isNaN(avgSyncDuration)) {
|
if (!isNaN(avgSyncDuration)) {
|
||||||
if (Math.random() >= 0.5) {
|
if (Math.random() >= 0.5) {
|
||||||
options.killAfter = avgSyncDuration * Math.random();
|
options.killAfter = avgSyncDuration * Math.random();
|
||||||
@ -2164,8 +2164,8 @@ async function execRandomCommand(client) {
|
|||||||
[
|
[
|
||||||
async () => {
|
async () => {
|
||||||
// UPDATE RANDOM ITEM
|
// UPDATE RANDOM ITEM
|
||||||
let items = await clientItems(client);
|
const items = await clientItems(client);
|
||||||
let item = randomNote(items);
|
const item = randomNote(items);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
return execCommand(client, `set ${item.id} title "${randomWord()}"`);
|
return execCommand(client, `set ${item.id} title "${randomWord()}"`);
|
||||||
@ -2175,12 +2175,12 @@ async function execRandomCommand(client) {
|
|||||||
[
|
[
|
||||||
async () => {
|
async () => {
|
||||||
// ADD TAG
|
// ADD TAG
|
||||||
let items = await clientItems(client);
|
const items = await clientItems(client);
|
||||||
let note = randomNote(items);
|
const note = randomNote(items);
|
||||||
if (!note) return;
|
if (!note) return;
|
||||||
|
|
||||||
let tag = randomTag(items);
|
const tag = randomTag(items);
|
||||||
let tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title;
|
const tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title;
|
||||||
|
|
||||||
return execCommand(client, `tag add ${tagTitle} ${note.id}`);
|
return execCommand(client, `tag add ${tagTitle} ${note.id}`);
|
||||||
},
|
},
|
||||||
@ -2191,7 +2191,7 @@ async function execRandomCommand(client) {
|
|||||||
let cmd = null;
|
let cmd = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
cmd = randomElement(possibleCommands);
|
cmd = randomElement(possibleCommands);
|
||||||
let r = 1 + Math.floor(Math.random() * 100);
|
const r = 1 + Math.floor(Math.random() * 100);
|
||||||
if (r <= cmd[1]) break;
|
if (r <= cmd[1]) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2210,7 +2210,7 @@ function averageSyncDuration() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomNextCheckTime() {
|
function randomNextCheckTime() {
|
||||||
let output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
|
const output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
|
||||||
logger.info(`Next sync check: ${time.unixMsToIso(output)} (${Math.round((output - time.unixMs()) / 1000)} sec.)`);
|
logger.info(`Next sync check: ${time.unixMsToIso(output)} (${Math.round((output - time.unixMs()) / 1000)} sec.)`);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -2223,11 +2223,11 @@ function findItem(items, itemId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function compareItems(item1, item2) {
|
function compareItems(item1, item2) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let n in item1) {
|
for (const n in item1) {
|
||||||
if (!item1.hasOwnProperty(n)) continue;
|
if (!item1.hasOwnProperty(n)) continue;
|
||||||
let p1 = item1[n];
|
const p1 = item1[n];
|
||||||
let p2 = item2[n];
|
const p2 = item2[n];
|
||||||
|
|
||||||
if (n == 'notes_') {
|
if (n == 'notes_') {
|
||||||
p1.sort();
|
p1.sort();
|
||||||
@ -2243,13 +2243,13 @@ function compareItems(item1, item2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findMissingItems_(items1, items2) {
|
function findMissingItems_(items1, items2) {
|
||||||
let output = [];
|
const output = [];
|
||||||
|
|
||||||
for (let i = 0; i < items1.length; i++) {
|
for (let i = 0; i < items1.length; i++) {
|
||||||
let item1 = items1[i];
|
const item1 = items1[i];
|
||||||
let found = false;
|
let found = false;
|
||||||
for (let j = 0; j < items2.length; j++) {
|
for (let j = 0; j < items2.length; j++) {
|
||||||
let item2 = items2[j];
|
const item2 = items2[j];
|
||||||
if (item1.id == item2.id) {
|
if (item1.id == item2.id) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@ -2269,33 +2269,33 @@ function findMissingItems(items1, items2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function compareClientItems(clientItems) {
|
async function compareClientItems(clientItems) {
|
||||||
let itemCounts = [];
|
const itemCounts = [];
|
||||||
for (let i = 0; i < clientItems.length; i++) {
|
for (let i = 0; i < clientItems.length; i++) {
|
||||||
let items = clientItems[i];
|
const items = clientItems[i];
|
||||||
itemCounts.push(items.length);
|
itemCounts.push(items.length);
|
||||||
}
|
}
|
||||||
logger.info(`Item count: ${itemCounts.join(', ')}`);
|
logger.info(`Item count: ${itemCounts.join(', ')}`);
|
||||||
|
|
||||||
let missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
const missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
||||||
if (missingItems[0].length || missingItems[1].length) {
|
if (missingItems[0].length || missingItems[1].length) {
|
||||||
logger.error('Items are different');
|
logger.error('Items are different');
|
||||||
logger.error(missingItems);
|
logger.error(missingItems);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let differences = [];
|
const differences = [];
|
||||||
let items = clientItems[0];
|
const items = clientItems[0];
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
let item1 = items[i];
|
const item1 = items[i];
|
||||||
for (let clientId = 1; clientId < clientItems.length; clientId++) {
|
for (let clientId = 1; clientId < clientItems.length; clientId++) {
|
||||||
let item2 = findItem(clientItems[clientId], item1.id);
|
const item2 = findItem(clientItems[clientId], item1.id);
|
||||||
if (!item2) {
|
if (!item2) {
|
||||||
logger.error(`Item not found on client ${clientId}:`);
|
logger.error(`Item not found on client ${clientId}:`);
|
||||||
logger.error(item1);
|
logger.error(item1);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let diff = compareItems(item1, item2);
|
const diff = compareItems(item1, item2);
|
||||||
if (diff.length) {
|
if (diff.length) {
|
||||||
differences.push({
|
differences.push({
|
||||||
item1: JSON.stringify(item1),
|
item1: JSON.stringify(item1),
|
||||||
@ -2315,7 +2315,7 @@ async function compareClientItems(clientItems) {
|
|||||||
async function main() {
|
async function main() {
|
||||||
await fs.remove(syncDir);
|
await fs.remove(syncDir);
|
||||||
|
|
||||||
let clients = await createClients();
|
const clients = await createClients();
|
||||||
let clientId = 0;
|
let clientId = 0;
|
||||||
|
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
@ -2348,7 +2348,7 @@ async function main() {
|
|||||||
|
|
||||||
if (state == 'syncCheck') {
|
if (state == 'syncCheck') {
|
||||||
state = 'waitForSyncCheck';
|
state = 'waitForSyncCheck';
|
||||||
let clientItems = [];
|
const clientItems = [];
|
||||||
// Up to 3 sync operations must be performed by each clients in order for them
|
// Up to 3 sync operations must be performed by each clients in order for them
|
||||||
// to be perfectly in sync - in order for each items to send their changes
|
// to be perfectly in sync - in order for each items to send their changes
|
||||||
// and get those from the other clients, and to also get changes that are
|
// and get those from the other clients, and to also get changes that are
|
||||||
@ -2356,12 +2356,12 @@ async function main() {
|
|||||||
// with another one).
|
// with another one).
|
||||||
for (let loopCount = 0; loopCount < 3; loopCount++) {
|
for (let loopCount = 0; loopCount < 3; loopCount++) {
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
let beforeTime = time.unixMs();
|
const beforeTime = time.unixMs();
|
||||||
await execCommand(clients[i], 'sync');
|
await execCommand(clients[i], 'sync');
|
||||||
syncDurations.push(time.unixMs() - beforeTime);
|
syncDurations.push(time.unixMs() - beforeTime);
|
||||||
if (syncDurations.length > 20) syncDurations.splice(0, 1);
|
if (syncDurations.length > 20) syncDurations.splice(0, 1);
|
||||||
if (loopCount === 2) {
|
if (loopCount === 2) {
|
||||||
let dump = await execCommand(clients[i], 'dump');
|
const dump = await execCommand(clients[i], 'dump');
|
||||||
clientItems[i] = JSON.parse(dump);
|
clientItems[i] = JSON.parse(dump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class FolderListWidget extends ListWidget {
|
|||||||
this.trimItemTitle = false;
|
this.trimItemTitle = false;
|
||||||
|
|
||||||
this.itemRenderer = item => {
|
this.itemRenderer = item => {
|
||||||
let output = [];
|
const output = [];
|
||||||
if (item === '-') {
|
if (item === '-') {
|
||||||
output.push('-'.repeat(this.innerWidth));
|
output.push('-'.repeat(this.innerWidth));
|
||||||
} else if (item.type_ === Folder.modelType()) {
|
} else if (item.type_ === Folder.modelType()) {
|
||||||
@ -121,7 +121,7 @@ class FolderListWidget extends ListWidget {
|
|||||||
|
|
||||||
folderHasChildren_(folders, folderId) {
|
folderHasChildren_(folders, folderId) {
|
||||||
for (let i = 0; i < folders.length; i++) {
|
for (let i = 0; i < folders.length; i++) {
|
||||||
let folder = folders[i];
|
const folder = folders[i];
|
||||||
if (folder.parent_id === folderId) return true;
|
if (folder.parent_id === folderId) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -106,7 +106,7 @@ class StatusBarWidget extends BaseWidget {
|
|||||||
|
|
||||||
const isSecurePrompt = !!this.promptState_.secure;
|
const isSecurePrompt = !!this.promptState_.secure;
|
||||||
|
|
||||||
let options = {
|
const options = {
|
||||||
cancelable: true,
|
cancelable: true,
|
||||||
history: this.history,
|
history: this.history,
|
||||||
default: this.promptState_.initialText,
|
default: this.promptState_.initialText,
|
||||||
|
@ -6,11 +6,11 @@ const MAX_WIDTH = 78;
|
|||||||
const INDENT = ' ';
|
const INDENT = ' ';
|
||||||
|
|
||||||
function renderTwoColumnData(options, baseIndent, width) {
|
function renderTwoColumnData(options, baseIndent, width) {
|
||||||
let output = [];
|
const output = [];
|
||||||
const optionColWidth = getOptionColWidth(options);
|
const optionColWidth = getOptionColWidth(options);
|
||||||
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
for (let i = 0; i < options.length; i++) {
|
||||||
let option = options[i];
|
const option = options[i];
|
||||||
const flag = option[0];
|
const flag = option[0];
|
||||||
const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2);
|
const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2);
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ function renderCommandHelp(cmd, width = null) {
|
|||||||
|
|
||||||
const baseIndent = '';
|
const baseIndent = '';
|
||||||
|
|
||||||
let output = [];
|
const output = [];
|
||||||
output.push(baseIndent + cmd.usage());
|
output.push(baseIndent + cmd.usage());
|
||||||
output.push('');
|
output.push('');
|
||||||
output.push(wrap(cmd.description(), baseIndent + INDENT, width));
|
output.push(wrap(cmd.description(), baseIndent + INDENT, width));
|
||||||
@ -42,7 +42,7 @@ function renderCommandHelp(cmd, width = null) {
|
|||||||
|
|
||||||
if (cmd.name() === 'config') {
|
if (cmd.name() === 'config') {
|
||||||
const renderMetadata = md => {
|
const renderMetadata = md => {
|
||||||
let desc = [];
|
const desc = [];
|
||||||
|
|
||||||
if (md.label) {
|
if (md.label) {
|
||||||
let label = md.label();
|
let label = md.label();
|
||||||
@ -77,7 +77,7 @@ function renderCommandHelp(cmd, width = null) {
|
|||||||
output.push(_('Possible keys/values:'));
|
output.push(_('Possible keys/values:'));
|
||||||
output.push('');
|
output.push('');
|
||||||
|
|
||||||
let keysValues = [];
|
const keysValues = [];
|
||||||
const keys = Setting.keys(true, 'cli');
|
const keys = Setting.keys(true, 'cli');
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
if (keysValues.length) keysValues.push(['', '']);
|
if (keysValues.length) keysValues.push(['', '']);
|
||||||
|
@ -54,7 +54,7 @@ shimInit();
|
|||||||
const application = app();
|
const application = app();
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
var rl = require('readline').createInterface({
|
const rl = require('readline').createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
output: process.stdout,
|
output: process.stdout,
|
||||||
});
|
});
|
||||||
|
@ -14,14 +14,14 @@ describe('InteropService_Importer_Md: importLocalImages', function() {
|
|||||||
it('should import linked files and modify tags appropriately', async function() {
|
it('should import linked files and modify tags appropriately', async function() {
|
||||||
const tagNonExistentFile = '';
|
const tagNonExistentFile = '';
|
||||||
const note = await importer.importFile(`${__dirname}/md_to_md/sample.md`, 'notebook');
|
const note = await importer.importFile(`${__dirname}/md_to_md/sample.md`, 'notebook');
|
||||||
let items = await Note.linkedItems(note.body);
|
const items = await Note.linkedItems(note.body);
|
||||||
expect(items.length).toBe(2);
|
expect(items.length).toBe(2);
|
||||||
const inexistentLinkUnchanged = note.body.includes(tagNonExistentFile);
|
const inexistentLinkUnchanged = note.body.includes(tagNonExistentFile);
|
||||||
expect(inexistentLinkUnchanged).toBe(true);
|
expect(inexistentLinkUnchanged).toBe(true);
|
||||||
});
|
});
|
||||||
it('should only create 1 resource for duplicate links, all tags should be updated', async function() {
|
it('should only create 1 resource for duplicate links, all tags should be updated', async function() {
|
||||||
const note = await importer.importFile(`${__dirname}/md_to_md/sample-duplicate-links.md`, 'notebook');
|
const note = await importer.importFile(`${__dirname}/md_to_md/sample-duplicate-links.md`, 'notebook');
|
||||||
let items = await Note.linkedItems(note.body);
|
const items = await Note.linkedItems(note.body);
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
const reg = new RegExp(items[0].id, 'g');
|
const reg = new RegExp(items[0].id, 'g');
|
||||||
const matched = note.body.match(reg);
|
const matched = note.body.match(reg);
|
||||||
@ -29,12 +29,12 @@ describe('InteropService_Importer_Md: importLocalImages', function() {
|
|||||||
});
|
});
|
||||||
it('should import linked files and modify tags appropriately when link is also in alt text', async function() {
|
it('should import linked files and modify tags appropriately when link is also in alt text', async function() {
|
||||||
const note = await importer.importFile(`${__dirname}/md_to_md/sample-link-in-alt-text.md`, 'notebook');
|
const note = await importer.importFile(`${__dirname}/md_to_md/sample-link-in-alt-text.md`, 'notebook');
|
||||||
let items = await Note.linkedItems(note.body);
|
const items = await Note.linkedItems(note.body);
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
});
|
});
|
||||||
it('should passthrough unchanged if no links present', async function() {
|
it('should passthrough unchanged if no links present', async function() {
|
||||||
const note = await importer.importFile(`${__dirname}/md_to_md/sample-no-links.md`, 'notebook');
|
const note = await importer.importFile(`${__dirname}/md_to_md/sample-no-links.md`, 'notebook');
|
||||||
let items = await Note.linkedItems(note.body);
|
const items = await Note.linkedItems(note.body);
|
||||||
expect(items.length).toBe(0);
|
expect(items.length).toBe(0);
|
||||||
expect(note.body).toContain('Unidentified vessel travelling at sub warp speed, bearing 235.7. Fluctuations in energy readings from it, Captain. All transporters off.');
|
expect(note.body).toContain('Unidentified vessel travelling at sub warp speed, bearing 235.7. Fluctuations in energy readings from it, Captain. All transporters off.');
|
||||||
});
|
});
|
||||||
|
@ -44,19 +44,19 @@ describe('integration_ShowAllNotes', function() {
|
|||||||
|
|
||||||
it('should show all notes', asyncTest(async () => {
|
it('should show all notes', asyncTest(async () => {
|
||||||
// setup
|
// setup
|
||||||
let folders = await createNTestFolders(3);
|
const folders = await createNTestFolders(3);
|
||||||
Folder.moveToFolder(id(folders[2]), id(folders[1])); // subfolder
|
Folder.moveToFolder(id(folders[2]), id(folders[1])); // subfolder
|
||||||
await time.msleep(100);
|
await time.msleep(100);
|
||||||
let notes0 = await createNTestNotes(3, folders[0]);
|
const notes0 = await createNTestNotes(3, folders[0]);
|
||||||
let notes1 = await createNTestNotes(3, folders[1]);
|
const notes1 = await createNTestNotes(3, folders[1]);
|
||||||
let notes2 = await createNTestNotes(3, folders[2]);
|
const notes2 = await createNTestNotes(3, folders[2]);
|
||||||
|
|
||||||
// TEST ACTION: View all-notes
|
// TEST ACTION: View all-notes
|
||||||
testApp.dispatch({ type: 'SMART_FILTER_SELECT', id: ALL_NOTES_FILTER_ID });
|
testApp.dispatch({ type: 'SMART_FILTER_SELECT', id: ALL_NOTES_FILTER_ID });
|
||||||
await time.msleep(100);
|
await time.msleep(100);
|
||||||
|
|
||||||
// check: all the notes are shown
|
// check: all the notes are shown
|
||||||
let state = testApp.store().getState();
|
const state = testApp.store().getState();
|
||||||
expect(state.notesParentType).toEqual('SmartFilter');
|
expect(state.notesParentType).toEqual('SmartFilter');
|
||||||
expect(state.selectedSmartFilterId).toEqual(ALL_NOTES_FILTER_ID);
|
expect(state.selectedSmartFilterId).toEqual(ALL_NOTES_FILTER_ID);
|
||||||
expect(sortedIds(state.notes)).toEqual(sortedIds(notes0.concat(notes1).concat(notes2)));
|
expect(sortedIds(state.notes)).toEqual(sortedIds(notes0.concat(notes1).concat(notes2)));
|
||||||
@ -64,9 +64,9 @@ describe('integration_ShowAllNotes', function() {
|
|||||||
|
|
||||||
it('should show retain note selection when going from a folder to all-notes', asyncTest(async () => {
|
it('should show retain note selection when going from a folder to all-notes', asyncTest(async () => {
|
||||||
// setup
|
// setup
|
||||||
let folders = await createNTestFolders(2);
|
const folders = await createNTestFolders(2);
|
||||||
let notes0 = await createNTestNotes(3, folders[0]);
|
const notes0 = await createNTestNotes(3, folders[0]);
|
||||||
let notes1 = await createNTestNotes(3, folders[1]);
|
const notes1 = await createNTestNotes(3, folders[1]);
|
||||||
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) });
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) });
|
||||||
await time.msleep(100);
|
await time.msleep(100);
|
||||||
testApp.dispatch({ type: 'NOTE_SELECT', id: id(notes1[1]) });
|
testApp.dispatch({ type: 'NOTE_SELECT', id: id(notes1[1]) });
|
||||||
|
@ -8,27 +8,27 @@ const Tag = require('lib/models/Tag.js');
|
|||||||
const { time } = require('lib/time-utils.js');
|
const { time } = require('lib/time-utils.js');
|
||||||
|
|
||||||
async function createNTestFolders(n) {
|
async function createNTestFolders(n) {
|
||||||
let folders = [];
|
const folders = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let folder = await Folder.save({ title: 'folder' });
|
const folder = await Folder.save({ title: 'folder' });
|
||||||
folders.push(folder);
|
folders.push(folder);
|
||||||
}
|
}
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNTestNotes(n, folder) {
|
async function createNTestNotes(n, folder) {
|
||||||
let notes = [];
|
const notes = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let note = await Note.save({ title: 'note', parent_id: folder.id, is_conflict: 0 });
|
const note = await Note.save({ title: 'note', parent_id: folder.id, is_conflict: 0 });
|
||||||
notes.push(note);
|
notes.push(note);
|
||||||
}
|
}
|
||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNTestTags(n) {
|
async function createNTestTags(n) {
|
||||||
let tags = [];
|
const tags = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let tag = await Tag.save({ title: 'tag' });
|
const tag = await Tag.save({ title: 'tag' });
|
||||||
tags.push(tag);
|
tags.push(tag);
|
||||||
}
|
}
|
||||||
return tags;
|
return tags;
|
||||||
@ -58,9 +58,9 @@ describe('integration_TagList', function() {
|
|||||||
// the tag list should be cleared if the next note has no tags
|
// the tag list should be cleared if the next note has no tags
|
||||||
it('should clear tag list when a note is deleted', asyncTest(async () => {
|
it('should clear tag list when a note is deleted', asyncTest(async () => {
|
||||||
// setup and select the note
|
// setup and select the note
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let tags = await createNTestTags(3);
|
const tags = await createNTestTags(3);
|
||||||
|
|
||||||
await Tag.addNote(tags[2].id, notes[2].id);
|
await Tag.addNote(tags[2].id, notes[2].id);
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ describe('integration_TagList', function() {
|
|||||||
// the tag list should be updated if the next note has tags
|
// the tag list should be updated if the next note has tags
|
||||||
it('should update tag list when a note is deleted', asyncTest(async () => {
|
it('should update tag list when a note is deleted', asyncTest(async () => {
|
||||||
// set up and select the note
|
// set up and select the note
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let tags = await createNTestTags(3);
|
const tags = await createNTestTags(3);
|
||||||
|
|
||||||
await Tag.addNote(tags[1].id, notes[1].id);
|
await Tag.addNote(tags[1].id, notes[1].id);
|
||||||
await Tag.addNote(tags[0].id, notes[0].id);
|
await Tag.addNote(tags[0].id, notes[0].id);
|
||||||
@ -130,8 +130,8 @@ describe('integration_TagList', function() {
|
|||||||
|
|
||||||
// check the tag list is updated
|
// check the tag list is updated
|
||||||
state = testApp.store().getState();
|
state = testApp.store().getState();
|
||||||
let tagIds = state.selectedNoteTags.map(n => n.id).sort();
|
const tagIds = state.selectedNoteTags.map(n => n.id).sort();
|
||||||
let expectedTagIds = [tags[0].id, tags[2].id].sort();
|
const expectedTagIds = [tags[0].id, tags[2].id].sort();
|
||||||
expect(state.selectedNoteTags.length).toEqual(2);
|
expect(state.selectedNoteTags.length).toEqual(2);
|
||||||
expect(tagIds).toEqual(expectedTagIds);
|
expect(tagIds).toEqual(expectedTagIds);
|
||||||
}));
|
}));
|
||||||
|
@ -16,8 +16,8 @@ process.on('unhandledRejection', (reason, p) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function allItems() {
|
async function allItems() {
|
||||||
let folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
return folders.concat(notes);
|
return folders.concat(notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,27 +32,27 @@ describe('models_BaseItem', function() {
|
|||||||
// This is to handle the case where a property is removed from a BaseItem table - in that case files in
|
// This is to handle the case where a property is removed from a BaseItem table - in that case files in
|
||||||
// the sync target will still have the old property but we don't need it locally.
|
// the sync target will still have the old property but we don't need it locally.
|
||||||
it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => {
|
it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder1' });
|
const folder = await Folder.save({ title: 'folder1' });
|
||||||
|
|
||||||
let serialized = await Folder.serialize(folder);
|
let serialized = await Folder.serialize(folder);
|
||||||
serialized += '\nignore_me: true';
|
serialized += '\nignore_me: true';
|
||||||
|
|
||||||
let unserialized = await Folder.unserialize(serialized);
|
const unserialized = await Folder.unserialize(serialized);
|
||||||
|
|
||||||
expect('ignore_me' in unserialized).toBe(false);
|
expect('ignore_me' in unserialized).toBe(false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not modify title when unserializing', asyncTest(async () => {
|
it('should not modify title when unserializing', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: '' });
|
const folder1 = await Folder.save({ title: '' });
|
||||||
let folder2 = await Folder.save({ title: 'folder1' });
|
const folder2 = await Folder.save({ title: 'folder1' });
|
||||||
|
|
||||||
let serialized1 = await Folder.serialize(folder1);
|
const serialized1 = await Folder.serialize(folder1);
|
||||||
let unserialized1 = await Folder.unserialize(serialized1);
|
const unserialized1 = await Folder.unserialize(serialized1);
|
||||||
|
|
||||||
expect(unserialized1.title).toBe(folder1.title);
|
expect(unserialized1.title).toBe(folder1.title);
|
||||||
|
|
||||||
let serialized2 = await Folder.serialize(folder2);
|
const serialized2 = await Folder.serialize(folder2);
|
||||||
let unserialized2 = await Folder.unserialize(serialized2);
|
const unserialized2 = await Folder.unserialize(serialized2);
|
||||||
|
|
||||||
expect(unserialized2.title).toBe(folder2.title);
|
expect(unserialized2.title).toBe(folder2.title);
|
||||||
}));
|
}));
|
||||||
|
@ -14,8 +14,8 @@ process.on('unhandledRejection', (reason, p) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function allItems() {
|
async function allItems() {
|
||||||
let folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
return folders.concat(notes);
|
return folders.concat(notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,10 +28,10 @@ describe('models_Folder', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should tell if a notebook can be nested under another one', asyncTest(async () => {
|
it('should tell if a notebook can be nested under another one', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'folder1' });
|
const f1 = await Folder.save({ title: 'folder1' });
|
||||||
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
||||||
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
||||||
let f4 = await Folder.save({ title: 'folder4' });
|
const f4 = await Folder.save({ title: 'folder4' });
|
||||||
|
|
||||||
expect(await Folder.canNestUnder(f1.id, f2.id)).toBe(false);
|
expect(await Folder.canNestUnder(f1.id, f2.id)).toBe(false);
|
||||||
expect(await Folder.canNestUnder(f2.id, f2.id)).toBe(false);
|
expect(await Folder.canNestUnder(f2.id, f2.id)).toBe(false);
|
||||||
@ -44,9 +44,9 @@ describe('models_Folder', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should recursively delete notes and sub-notebooks', asyncTest(async () => {
|
it('should recursively delete notes and sub-notebooks', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'folder1' });
|
const f1 = await Folder.save({ title: 'folder1' });
|
||||||
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
||||||
let n1 = await Note.save({ title: 'note1', parent_id: f2.id });
|
const n1 = await Note.save({ title: 'note1', parent_id: f2.id });
|
||||||
|
|
||||||
await Folder.delete(f1.id);
|
await Folder.delete(f1.id);
|
||||||
|
|
||||||
@ -57,10 +57,10 @@ describe('models_Folder', function() {
|
|||||||
it('should sort by last modified, based on content', asyncTest(async () => {
|
it('should sort by last modified, based on content', asyncTest(async () => {
|
||||||
let folders;
|
let folders;
|
||||||
|
|
||||||
let f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
|
const f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
|
||||||
let f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
|
const f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
|
||||||
let f3 = await Folder.save({ title: 'folder3' }); await sleep(0.1);
|
const f3 = await Folder.save({ title: 'folder3' }); await sleep(0.1);
|
||||||
let n1 = await Note.save({ title: 'note1', parent_id: f2.id });
|
const n1 = await Note.save({ title: 'note1', parent_id: f2.id });
|
||||||
|
|
||||||
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
||||||
expect(folders.length).toBe(3);
|
expect(folders.length).toBe(3);
|
||||||
@ -68,7 +68,7 @@ describe('models_Folder', function() {
|
|||||||
expect(folders[1].id).toBe(f3.id);
|
expect(folders[1].id).toBe(f3.id);
|
||||||
expect(folders[2].id).toBe(f1.id);
|
expect(folders[2].id).toBe(f1.id);
|
||||||
|
|
||||||
let n2 = await Note.save({ title: 'note1', parent_id: f1.id });
|
const n2 = await Note.save({ title: 'note1', parent_id: f1.id });
|
||||||
|
|
||||||
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
||||||
expect(folders[0].id).toBe(f1.id);
|
expect(folders[0].id).toBe(f1.id);
|
||||||
@ -91,10 +91,10 @@ describe('models_Folder', function() {
|
|||||||
it('should sort by last modified, based on content (sub-folders too)', asyncTest(async () => {
|
it('should sort by last modified, based on content (sub-folders too)', asyncTest(async () => {
|
||||||
let folders;
|
let folders;
|
||||||
|
|
||||||
let f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
|
const f1 = await Folder.save({ title: 'folder1' }); await sleep(0.1);
|
||||||
let f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
|
const f2 = await Folder.save({ title: 'folder2' }); await sleep(0.1);
|
||||||
let f3 = await Folder.save({ title: 'folder3', parent_id: f1.id }); await sleep(0.1);
|
const f3 = await Folder.save({ title: 'folder3', parent_id: f1.id }); await sleep(0.1);
|
||||||
let n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
||||||
|
|
||||||
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
||||||
expect(folders.length).toBe(3);
|
expect(folders.length).toBe(3);
|
||||||
@ -102,7 +102,7 @@ describe('models_Folder', function() {
|
|||||||
expect(folders[1].id).toBe(f3.id);
|
expect(folders[1].id).toBe(f3.id);
|
||||||
expect(folders[2].id).toBe(f2.id);
|
expect(folders[2].id).toBe(f2.id);
|
||||||
|
|
||||||
let n2 = await Note.save({ title: 'note2', parent_id: f2.id });
|
const n2 = await Note.save({ title: 'note2', parent_id: f2.id });
|
||||||
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
||||||
|
|
||||||
expect(folders[0].id).toBe(f2.id);
|
expect(folders[0].id).toBe(f2.id);
|
||||||
@ -116,8 +116,8 @@ describe('models_Folder', function() {
|
|||||||
expect(folders[1].id).toBe(f3.id);
|
expect(folders[1].id).toBe(f3.id);
|
||||||
expect(folders[2].id).toBe(f2.id);
|
expect(folders[2].id).toBe(f2.id);
|
||||||
|
|
||||||
let f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); await sleep(0.1);
|
const f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); await sleep(0.1);
|
||||||
let n3 = await Note.save({ title: 'note3', parent_id: f4.id });
|
const n3 = await Note.save({ title: 'note3', parent_id: f4.id });
|
||||||
|
|
||||||
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
folders = await Folder.orderByLastModified(await Folder.all(), 'desc');
|
||||||
expect(folders.length).toBe(4);
|
expect(folders.length).toBe(4);
|
||||||
@ -128,14 +128,14 @@ describe('models_Folder', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should add node counts', asyncTest(async () => {
|
it('should add node counts', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'folder1' });
|
const f1 = await Folder.save({ title: 'folder1' });
|
||||||
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
||||||
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
||||||
let f4 = await Folder.save({ title: 'folder4' });
|
const f4 = await Folder.save({ title: 'folder4' });
|
||||||
|
|
||||||
let n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
||||||
let n2 = await Note.save({ title: 'note1', parent_id: f3.id });
|
const n2 = await Note.save({ title: 'note1', parent_id: f3.id });
|
||||||
let n3 = await Note.save({ title: 'note1', parent_id: f1.id });
|
const n3 = await Note.save({ title: 'note1', parent_id: f1.id });
|
||||||
|
|
||||||
const folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
await Folder.addNoteCounts(folders);
|
await Folder.addNoteCounts(folders);
|
||||||
@ -152,17 +152,17 @@ describe('models_Folder', function() {
|
|||||||
|
|
||||||
it('should not count completed to-dos', asyncTest(async () => {
|
it('should not count completed to-dos', asyncTest(async () => {
|
||||||
|
|
||||||
let f1 = await Folder.save({ title: 'folder1' });
|
const f1 = await Folder.save({ title: 'folder1' });
|
||||||
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
||||||
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
||||||
let f4 = await Folder.save({ title: 'folder4' });
|
const f4 = await Folder.save({ title: 'folder4' });
|
||||||
|
|
||||||
let n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
const n1 = await Note.save({ title: 'note1', parent_id: f3.id });
|
||||||
let n2 = await Note.save({ title: 'note2', parent_id: f3.id });
|
const n2 = await Note.save({ title: 'note2', parent_id: f3.id });
|
||||||
let n3 = await Note.save({ title: 'note3', parent_id: f1.id });
|
const n3 = await Note.save({ title: 'note3', parent_id: f1.id });
|
||||||
let n4 = await Note.save({ title: 'note4', parent_id: f3.id, is_todo: true, todo_completed: 0 });
|
const n4 = await Note.save({ title: 'note4', parent_id: f3.id, is_todo: true, todo_completed: 0 });
|
||||||
let n5 = await Note.save({ title: 'note5', parent_id: f3.id, is_todo: true, todo_completed: 999 });
|
const n5 = await Note.save({ title: 'note5', parent_id: f3.id, is_todo: true, todo_completed: 999 });
|
||||||
let n6 = await Note.save({ title: 'note6', parent_id: f3.id, is_todo: true, todo_completed: 999 });
|
const n6 = await Note.save({ title: 'note6', parent_id: f3.id, is_todo: true, todo_completed: 999 });
|
||||||
|
|
||||||
const folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
await Folder.addNoteCounts(folders, false);
|
await Folder.addNoteCounts(folders, false);
|
||||||
@ -179,9 +179,9 @@ describe('models_Folder', function() {
|
|||||||
|
|
||||||
it('should recursively find folder path', asyncTest(async () => {
|
it('should recursively find folder path', asyncTest(async () => {
|
||||||
|
|
||||||
let f1 = await Folder.save({ title: 'folder1' });
|
const f1 = await Folder.save({ title: 'folder1' });
|
||||||
let f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id });
|
||||||
let f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id });
|
||||||
|
|
||||||
const folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
const folderPath = await Folder.folderPath(folders, f3.id);
|
const folderPath = await Folder.folderPath(folders, f3.id);
|
||||||
|
@ -23,8 +23,8 @@ describe('models_Note', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should find resource and note IDs', asyncTest(async () => {
|
it('should find resource and note IDs', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
|
let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
|
||||||
|
|
||||||
let items = await Note.linkedItems(note2.body);
|
let items = await Note.linkedItems(note2.body);
|
||||||
@ -69,7 +69,7 @@ describe('models_Note', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should change the type of notes', asyncTest(async () => {
|
it('should change the type of notes', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ describe('models_Note', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should serialize and unserialize without modifying data', asyncTest(async () => {
|
it('should serialize and unserialize without modifying data', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
const testCases = [
|
const testCases = [
|
||||||
[{ title: '', body: 'Body and no title\nSecond line\nThird Line', parent_id: folder1.id },
|
[{ title: '', body: 'Body and no title\nSecond line\nThird Line', parent_id: folder1.id },
|
||||||
'', 'Body and no title\nSecond line\nThird Line'],
|
'', 'Body and no title\nSecond line\nThird Line'],
|
||||||
@ -107,9 +107,9 @@ describe('models_Note', function() {
|
|||||||
const expectedTitle = t[1];
|
const expectedTitle = t[1];
|
||||||
const expectedBody = t[1];
|
const expectedBody = t[1];
|
||||||
|
|
||||||
let note1 = await Note.save(input);
|
const note1 = await Note.save(input);
|
||||||
let serialized = await Note.serialize(note1);
|
const serialized = await Note.serialize(note1);
|
||||||
let unserialized = await Note.unserialize(serialized);
|
const unserialized = await Note.unserialize(serialized);
|
||||||
|
|
||||||
expect(unserialized.title).toBe(input.title);
|
expect(unserialized.title).toBe(input.title);
|
||||||
expect(unserialized.body).toBe(input.body);
|
expect(unserialized.body).toBe(input.body);
|
||||||
@ -117,10 +117,10 @@ describe('models_Note', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should reset fields for a duplicate', asyncTest(async () => {
|
it('should reset fields for a duplicate', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'note', parent_id: folder1.id });
|
||||||
|
|
||||||
let duplicatedNote = await Note.duplicate(note1.id);
|
const duplicatedNote = await Note.duplicate(note1.id);
|
||||||
|
|
||||||
expect(duplicatedNote !== note1).toBe(true);
|
expect(duplicatedNote !== note1).toBe(true);
|
||||||
expect(duplicatedNote.created_time !== note1.created_time).toBe(true);
|
expect(duplicatedNote.created_time !== note1.created_time).toBe(true);
|
||||||
|
@ -27,30 +27,30 @@ describe('models_Resource', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have a "done" fetch_status when created locally', asyncTest(async () => {
|
it('should have a "done" fetch_status when created locally', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, testImagePath);
|
await shim.attachFileToNote(note1, testImagePath);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
let ls = await Resource.localState(resource1);
|
const ls = await Resource.localState(resource1);
|
||||||
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should have a default local state', asyncTest(async () => {
|
it('should have a default local state', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, testImagePath);
|
await shim.attachFileToNote(note1, testImagePath);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
let ls = await Resource.localState(resource1);
|
const ls = await Resource.localState(resource1);
|
||||||
expect(!ls.id).toBe(true);
|
expect(!ls.id).toBe(true);
|
||||||
expect(ls.resource_id).toBe(resource1.id);
|
expect(ls.resource_id).toBe(resource1.id);
|
||||||
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should save and delete local state', asyncTest(async () => {
|
it('should save and delete local state', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, testImagePath);
|
await shim.attachFileToNote(note1, testImagePath);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
await Resource.setLocalState(resource1, { fetch_status: Resource.FETCH_STATUS_IDLE });
|
await Resource.setLocalState(resource1, { fetch_status: Resource.FETCH_STATUS_IDLE });
|
||||||
|
|
||||||
let ls = await Resource.localState(resource1);
|
let ls = await Resource.localState(resource1);
|
||||||
@ -63,13 +63,13 @@ describe('models_Resource', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should resize the resource if the image is below the required dimensions', asyncTest(async () => {
|
it('should resize the resource if the image is below the required dimensions', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
const previousMax = Resource.IMAGE_MAX_DIMENSION;
|
const previousMax = Resource.IMAGE_MAX_DIMENSION;
|
||||||
Resource.IMAGE_MAX_DIMENSION = 5;
|
Resource.IMAGE_MAX_DIMENSION = 5;
|
||||||
await shim.attachFileToNote(note1, testImagePath);
|
await shim.attachFileToNote(note1, testImagePath);
|
||||||
Resource.IMAGE_MAX_DIMENSION = previousMax;
|
Resource.IMAGE_MAX_DIMENSION = previousMax;
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
|
|
||||||
const originalStat = await shim.fsDriver().stat(testImagePath);
|
const originalStat = await shim.fsDriver().stat(testImagePath);
|
||||||
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));
|
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));
|
||||||
@ -78,10 +78,10 @@ describe('models_Resource', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not resize the resource if the image is below the required dimensions', asyncTest(async () => {
|
it('should not resize the resource if the image is below the required dimensions', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, testImagePath);
|
await shim.attachFileToNote(note1, testImagePath);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
|
|
||||||
const originalStat = await shim.fsDriver().stat(testImagePath);
|
const originalStat = await shim.fsDriver().stat(testImagePath);
|
||||||
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));
|
const newStat = await shim.fsDriver().stat(Resource.fullPath(resource1));
|
||||||
|
@ -24,8 +24,8 @@ describe('models_Tag', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add tags by title', asyncTest(async () => {
|
it('should add tags by title', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
|
|
||||||
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
|
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
|
||||||
|
|
||||||
@ -34,8 +34,8 @@ describe('models_Tag', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not allow renaming tag to existing tag names', asyncTest(async () => {
|
it('should not allow renaming tag to existing tag names', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
|
|
||||||
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
|
await Tag.setNoteTagsByTitles(note1.id, ['un', 'deux']);
|
||||||
|
|
||||||
@ -46,8 +46,8 @@ describe('models_Tag', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not return tags without notes', asyncTest(async () => {
|
it('should not return tags without notes', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
||||||
|
|
||||||
let tags = await Tag.allWithNotes();
|
let tags = await Tag.allWithNotes();
|
||||||
@ -60,9 +60,9 @@ describe('models_Tag', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should return tags with note counts', asyncTest(async () => {
|
it('should return tags with note counts', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
|
||||||
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
||||||
await Tag.setNoteTagsByTitles(note2.id, ['un']);
|
await Tag.setNoteTagsByTitles(note2.id, ['un']);
|
||||||
|
|
||||||
@ -83,10 +83,10 @@ describe('models_Tag', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should load individual tags with note count', asyncTest(async () => {
|
it('should load individual tags with note count', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
|
||||||
let tag = await Tag.save({ title: 'mytag' });
|
const tag = await Tag.save({ title: 'mytag' });
|
||||||
await Tag.addNote(tag.id, note1.id);
|
await Tag.addNote(tag.id, note1.id);
|
||||||
|
|
||||||
let tagWithCount = await Tag.loadWithCount(tag.id);
|
let tagWithCount = await Tag.loadWithCount(tag.id);
|
||||||
@ -98,16 +98,16 @@ describe('models_Tag', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get common tags for set of notes', asyncTest(async () => {
|
it('should get common tags for set of notes', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let taga = await Tag.save({ title: 'mytaga' });
|
const taga = await Tag.save({ title: 'mytaga' });
|
||||||
let tagb = await Tag.save({ title: 'mytagb' });
|
const tagb = await Tag.save({ title: 'mytagb' });
|
||||||
let tagc = await Tag.save({ title: 'mytagc' });
|
const tagc = await Tag.save({ title: 'mytagc' });
|
||||||
let tagd = await Tag.save({ title: 'mytagd' });
|
const tagd = await Tag.save({ title: 'mytagd' });
|
||||||
|
|
||||||
let note0 = await Note.save({ title: 'ma note 0', parent_id: folder1.id });
|
const note0 = await Note.save({ title: 'ma note 0', parent_id: folder1.id });
|
||||||
let note1 = await Note.save({ title: 'ma note 1', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note 1', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma note 2', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma note 2', parent_id: folder1.id });
|
||||||
let note3 = await Note.save({ title: 'ma note 3', parent_id: folder1.id });
|
const note3 = await Note.save({ title: 'ma note 3', parent_id: folder1.id });
|
||||||
|
|
||||||
await Tag.addNote(taga.id, note1.id);
|
await Tag.addNote(taga.id, note1.id);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const Note = require('lib/models/Note.js');
|
|||||||
const Tag = require('lib/models/Tag.js');
|
const Tag = require('lib/models/Tag.js');
|
||||||
const { reducer, defaultState, stateUtils } = require('lib/reducer.js');
|
const { reducer, defaultState, stateUtils } = require('lib/reducer.js');
|
||||||
|
|
||||||
function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags=null, selectedTagIndex=null) {
|
function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags = null, selectedTagIndex = null) {
|
||||||
let state = defaultState;
|
let state = defaultState;
|
||||||
|
|
||||||
if (selectedFolderIndex != null) {
|
if (selectedFolderIndex != null) {
|
||||||
@ -20,7 +20,7 @@ function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes,
|
|||||||
state = reducer(state, { type: 'NOTE_UPDATE_ALL', notes: notes, noteSource: 'test' });
|
state = reducer(state, { type: 'NOTE_UPDATE_ALL', notes: notes, noteSource: 'test' });
|
||||||
}
|
}
|
||||||
if (selectedNoteIndexes != null) {
|
if (selectedNoteIndexes != null) {
|
||||||
let selectedIds = [];
|
const selectedIds = [];
|
||||||
for (let i = 0; i < selectedNoteIndexes.length; i++) {
|
for (let i = 0; i < selectedNoteIndexes.length; i++) {
|
||||||
selectedIds.push(notes[selectedNoteIndexes[i]].id);
|
selectedIds.push(notes[selectedNoteIndexes[i]].id);
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createExpectedState(items, keepIndexes, selectedIndexes) {
|
function createExpectedState(items, keepIndexes, selectedIndexes) {
|
||||||
let expected = { items: [], selectedIds: [] };
|
const expected = { items: [], selectedIds: [] };
|
||||||
|
|
||||||
for (let i = 0; i < selectedIndexes.length; i++) {
|
for (let i = 0; i < selectedIndexes.length; i++) {
|
||||||
expected.selectedIds.push(items[selectedIndexes[i]].id);
|
expected.selectedIds.push(items[selectedIndexes[i]].id);
|
||||||
@ -48,8 +48,8 @@ function createExpectedState(items, keepIndexes, selectedIndexes) {
|
|||||||
return expected;
|
return expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIds(items, indexes=null) {
|
function getIds(items, indexes = null) {
|
||||||
let ids = [];
|
const ids = [];
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
if (indexes == null || i in indexes) {
|
if (indexes == null || i in indexes) {
|
||||||
ids.push(items[i].id);
|
ids.push(items[i].id);
|
||||||
@ -76,9 +76,9 @@ describe('Reducer', function() {
|
|||||||
// tests for NOTE_DELETE
|
// tests for NOTE_DELETE
|
||||||
it('should delete selected note', asyncTest(async () => {
|
it('should delete selected note', asyncTest(async () => {
|
||||||
// create 1 folder
|
// create 1 folder
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
// create 5 notes
|
// create 5 notes
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
// select the 1st folder and the 3rd note
|
// select the 1st folder and the 3rd note
|
||||||
let state = initTestState(folders, 0, notes, [2]);
|
let state = initTestState(folders, 0, notes, [2]);
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ describe('Reducer', function() {
|
|||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
||||||
|
|
||||||
// expect that the third note is missing, and the 4th note is now selected
|
// expect that the third note is missing, and the 4th note is now selected
|
||||||
let expected = createExpectedState(notes, [0,1,3,4], [3]);
|
const expected = createExpectedState(notes, [0,1,3,4], [3]);
|
||||||
|
|
||||||
// check the ids of all the remaining notes
|
// check the ids of all the remaining notes
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
@ -96,136 +96,136 @@ describe('Reducer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete selected note at top', asyncTest(async () => {
|
it('should delete selected note at top', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [1]);
|
let state = initTestState(folders, 0, notes, [1]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [1,2,3,4], [1]);
|
const expected = createExpectedState(notes, [1,2,3,4], [1]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete last remaining note', asyncTest(async () => {
|
it('should delete last remaining note', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(1, folders[0]);
|
const notes = await createNTestNotes(1, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [0]);
|
let state = initTestState(folders, 0, notes, [0]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[0].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [], []);
|
const expected = createExpectedState(notes, [], []);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete selected note at bottom', asyncTest(async () => {
|
it('should delete selected note at bottom', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [4]);
|
let state = initTestState(folders, 0, notes, [4]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,1,2,3], [3]);
|
const expected = createExpectedState(notes, [0,1,2,3], [3]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete note when a note below is selected', asyncTest(async () => {
|
it('should delete note when a note below is selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [3]);
|
let state = initTestState(folders, 0, notes, [3]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,2,3,4], [3]);
|
const expected = createExpectedState(notes, [0,2,3,4], [3]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete note when a note above is selected', asyncTest(async () => {
|
it('should delete note when a note above is selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [1]);
|
let state = initTestState(folders, 0, notes, [1]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,1,2,4], [1]);
|
const expected = createExpectedState(notes, [0,1,2,4], [1]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete selected notes', asyncTest(async () => {
|
it('should delete selected notes', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [1,2]);
|
let state = initTestState(folders, 0, notes, [1,2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,3,4], [3]);
|
const expected = createExpectedState(notes, [0,3,4], [3]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete note when a notes below it are selected', asyncTest(async () => {
|
it('should delete note when a notes below it are selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [3,4]);
|
let state = initTestState(folders, 0, notes, [3,4]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[1].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,2,3,4], [3,4]);
|
const expected = createExpectedState(notes, [0,2,3,4], [3,4]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete note when a notes above it are selected', asyncTest(async () => {
|
it('should delete note when a notes above it are selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [1,2]);
|
let state = initTestState(folders, 0, notes, [1,2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,1,2,4], [1,2]);
|
const expected = createExpectedState(notes, [0,1,2,4], [1,2]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete notes at end', asyncTest(async () => {
|
it('should delete notes at end', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [3,4]);
|
let state = initTestState(folders, 0, notes, [3,4]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[3].id });
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [0,1,2], [2]);
|
const expected = createExpectedState(notes, [0,1,2], [2]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete notes when non-contiguous selection', asyncTest(async () => {
|
it('should delete notes when non-contiguous selection', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(1);
|
const folders = await createNTestFolders(1);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 0, notes, [0,2,4]);
|
let state = initTestState(folders, 0, notes, [0,2,4]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
@ -233,7 +233,7 @@ describe('Reducer', function() {
|
|||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[2].id });
|
||||||
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
state = reducer(state, { type: 'NOTE_DELETE', id: notes[4].id });
|
||||||
|
|
||||||
let expected = createExpectedState(notes, [1,3], [1]);
|
const expected = createExpectedState(notes, [1,3], [1]);
|
||||||
|
|
||||||
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
expect(getIds(state.notes)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
expect(state.selectedNoteIds).toEqual(expected.selectedIds);
|
||||||
@ -241,42 +241,42 @@ describe('Reducer', function() {
|
|||||||
|
|
||||||
// tests for FOLDER_DELETE
|
// tests for FOLDER_DELETE
|
||||||
it('should delete selected notebook', asyncTest(async () => {
|
it('should delete selected notebook', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(5);
|
const folders = await createNTestFolders(5);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 2, notes, [2]);
|
let state = initTestState(folders, 2, notes, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
||||||
|
|
||||||
let expected = createExpectedState(folders, [0,1,3,4], [3]);
|
const expected = createExpectedState(folders, [0,1,3,4], [3]);
|
||||||
|
|
||||||
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete notebook when a book above is selected', asyncTest(async () => {
|
it('should delete notebook when a book above is selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(5);
|
const folders = await createNTestFolders(5);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 1, notes, [2]);
|
let state = initTestState(folders, 1, notes, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
||||||
|
|
||||||
let expected = createExpectedState(folders, [0,1,3,4], [1]);
|
const expected = createExpectedState(folders, [0,1,3,4], [1]);
|
||||||
|
|
||||||
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete notebook when a book below is selected', asyncTest(async () => {
|
it('should delete notebook when a book below is selected', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(5);
|
const folders = await createNTestFolders(5);
|
||||||
let notes = await createNTestNotes(5, folders[0]);
|
const notes = await createNTestNotes(5, folders[0]);
|
||||||
let state = initTestState(folders, 4, notes, [2]);
|
let state = initTestState(folders, 4, notes, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
state = reducer(state, { type: 'FOLDER_DELETE', id: folders[2].id });
|
||||||
|
|
||||||
let expected = createExpectedState(folders, [0,1,3,4], [4]);
|
const expected = createExpectedState(folders, [0,1,3,4], [4]);
|
||||||
|
|
||||||
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
expect(getIds(state.folders)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedFolderId).toEqual(expected.selectedIds[0]);
|
||||||
@ -284,47 +284,47 @@ describe('Reducer', function() {
|
|||||||
|
|
||||||
// tests for TAG_DELETE
|
// tests for TAG_DELETE
|
||||||
it('should delete selected tag', asyncTest(async () => {
|
it('should delete selected tag', asyncTest(async () => {
|
||||||
let tags = await createNTestTags(5);
|
const tags = await createNTestTags(5);
|
||||||
let state = initTestState(null, null, null, null, tags, [2]);
|
let state = initTestState(null, null, null, null, tags, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'TAG_DELETE', id: tags[2].id });
|
state = reducer(state, { type: 'TAG_DELETE', id: tags[2].id });
|
||||||
|
|
||||||
let expected = createExpectedState(tags, [0,1,3,4], [3]);
|
const expected = createExpectedState(tags, [0,1,3,4], [3]);
|
||||||
|
|
||||||
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete tag when a tag above is selected', asyncTest(async () => {
|
it('should delete tag when a tag above is selected', asyncTest(async () => {
|
||||||
let tags = await createNTestTags(5);
|
const tags = await createNTestTags(5);
|
||||||
let state = initTestState(null, null, null, null, tags, [2]);
|
let state = initTestState(null, null, null, null, tags, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'TAG_DELETE', id: tags[4].id });
|
state = reducer(state, { type: 'TAG_DELETE', id: tags[4].id });
|
||||||
|
|
||||||
let expected = createExpectedState(tags, [0,1,2,3], [2]);
|
const expected = createExpectedState(tags, [0,1,2,3], [2]);
|
||||||
|
|
||||||
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete tag when a tag below is selected', asyncTest(async () => {
|
it('should delete tag when a tag below is selected', asyncTest(async () => {
|
||||||
let tags = await createNTestTags(5);
|
const tags = await createNTestTags(5);
|
||||||
let state = initTestState(null, null, null, null, tags, [2]);
|
let state = initTestState(null, null, null, null, tags, [2]);
|
||||||
|
|
||||||
// test action
|
// test action
|
||||||
state = reducer(state, { type: 'TAG_DELETE', id: tags[0].id });
|
state = reducer(state, { type: 'TAG_DELETE', id: tags[0].id });
|
||||||
|
|
||||||
let expected = createExpectedState(tags, [1,2,3,4], [2]);
|
const expected = createExpectedState(tags, [1,2,3,4], [2]);
|
||||||
|
|
||||||
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
expect(getIds(state.tags)).toEqual(getIds(expected.items));
|
||||||
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
expect(state.selectedTagId).toEqual(expected.selectedIds[0]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should select all notes', asyncTest(async () => {
|
it('should select all notes', asyncTest(async () => {
|
||||||
let folders = await createNTestFolders(2);
|
const folders = await createNTestFolders(2);
|
||||||
let notes = [];
|
const notes = [];
|
||||||
for (let i = 0; i < folders.length; i++) {
|
for (let i = 0; i < folders.length; i++) {
|
||||||
notes.push(...await createNTestNotes(3, folders[i]));
|
notes.push(...await createNTestNotes(3, folders[i]));
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ describe('services_EncryptionService', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not upgrade master key if invalid password', asyncTest(async () => {
|
it('should not upgrade master key if invalid password', asyncTest(async () => {
|
||||||
let masterKey = await service.generateMasterKey('123456', {
|
const masterKey = await service.generateMasterKey('123456', {
|
||||||
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ describe('services_EncryptionService', function() {
|
|||||||
|
|
||||||
await service.unloadMasterKey(masterKey);
|
await service.unloadMasterKey(masterKey);
|
||||||
|
|
||||||
let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
|
const hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
|
||||||
|
|
||||||
expect(hasThrown).toBe(true);
|
expect(hasThrown).toBe(true);
|
||||||
}));
|
}));
|
||||||
@ -222,7 +222,7 @@ describe('services_EncryptionService', function() {
|
|||||||
let cipherText = await service.encryptString('some secret');
|
let cipherText = await service.encryptString('some secret');
|
||||||
cipherText += 'ABCDEFGHIJ';
|
cipherText += 'ABCDEFGHIJ';
|
||||||
|
|
||||||
let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
|
const hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText));
|
||||||
|
|
||||||
expect(hasThrown).toBe(true);
|
expect(hasThrown).toBe(true);
|
||||||
}));
|
}));
|
||||||
@ -232,10 +232,10 @@ describe('services_EncryptionService', function() {
|
|||||||
masterKey = await MasterKey.save(masterKey);
|
masterKey = await MasterKey.save(masterKey);
|
||||||
await service.loadMasterKey_(masterKey, '123456', true);
|
await service.loadMasterKey_(masterKey, '123456', true);
|
||||||
|
|
||||||
let folder = await Folder.save({ title: 'folder' });
|
const folder = await Folder.save({ title: 'folder' });
|
||||||
let note = await Note.save({ title: 'encrypted note', body: 'something', parent_id: folder.id });
|
const note = await Note.save({ title: 'encrypted note', body: 'something', parent_id: folder.id });
|
||||||
let serialized = await Note.serializeForSync(note);
|
const serialized = await Note.serializeForSync(note);
|
||||||
let deserialized = Note.filter(await Note.unserialize(serialized));
|
const deserialized = Note.filter(await Note.unserialize(serialized));
|
||||||
|
|
||||||
// Check that required properties are not encrypted
|
// Check that required properties are not encrypted
|
||||||
expect(deserialized.id).toBe(note.id);
|
expect(deserialized.id).toBe(note.id);
|
||||||
|
@ -59,7 +59,7 @@ describe('services_InteropService', function() {
|
|||||||
// Check that a new folder, with a new ID, has been created
|
// Check that a new folder, with a new ID, has been created
|
||||||
|
|
||||||
expect(await Folder.count()).toBe(1);
|
expect(await Folder.count()).toBe(1);
|
||||||
let folder2 = (await Folder.all())[0];
|
const folder2 = (await Folder.all())[0];
|
||||||
expect(folder2.id).not.toBe(folder1.id);
|
expect(folder2.id).not.toBe(folder1.id);
|
||||||
expect(folder2.title).toBe(folder1.title);
|
expect(folder2.title).toBe(folder1.title);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ describe('services_InteropService', function() {
|
|||||||
// As there was already a folder with the same title, check that the new one has been renamed
|
// As there was already a folder with the same title, check that the new one has been renamed
|
||||||
|
|
||||||
await Folder.delete(folder2.id);
|
await Folder.delete(folder2.id);
|
||||||
let folder3 = (await Folder.all())[0];
|
const folder3 = (await Folder.all())[0];
|
||||||
expect(await Folder.count()).toBe(1);
|
expect(await Folder.count()).toBe(1);
|
||||||
expect(folder3.title).not.toBe(folder2.title);
|
expect(folder3.title).not.toBe(folder2.title);
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
it('should export and import folders and notes', asyncTest(async () => {
|
it('should export and import folders and notes', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
@ -95,7 +95,7 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
expect(await Note.count()).toBe(1);
|
expect(await Note.count()).toBe(1);
|
||||||
let note2 = (await Note.all())[0];
|
let note2 = (await Note.all())[0];
|
||||||
let folder2 = (await Folder.all())[0];
|
const folder2 = (await Folder.all())[0];
|
||||||
|
|
||||||
expect(note1.parent_id).not.toBe(note2.parent_id);
|
expect(note1.parent_id).not.toBe(note2.parent_id);
|
||||||
expect(note1.id).not.toBe(note2.id);
|
expect(note1.id).not.toBe(note2.id);
|
||||||
@ -110,7 +110,7 @@ describe('services_InteropService', function() {
|
|||||||
await service.import({ path: filePath });
|
await service.import({ path: filePath });
|
||||||
|
|
||||||
note2 = (await Note.all())[0];
|
note2 = (await Note.all())[0];
|
||||||
let note3 = (await Note.all())[1];
|
const note3 = (await Note.all())[1];
|
||||||
|
|
||||||
expect(note2.id).not.toBe(note3.id);
|
expect(note2.id).not.toBe(note3.id);
|
||||||
expect(note2.parent_id).not.toBe(note3.parent_id);
|
expect(note2.parent_id).not.toBe(note3.parent_id);
|
||||||
@ -120,7 +120,7 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
it('should export and import notes to specific folder', asyncTest(async () => {
|
it('should export and import notes to specific folder', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
@ -140,8 +140,8 @@ describe('services_InteropService', function() {
|
|||||||
it('should export and import tags', asyncTest(async () => {
|
it('should export and import tags', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let tag1 = await Tag.save({ title: 'mon tag' });
|
let tag1 = await Tag.save({ title: 'mon tag' });
|
||||||
tag1 = await Tag.load(tag1.id);
|
tag1 = await Tag.load(tag1.id);
|
||||||
await Tag.addNote(tag1.id, note1.id);
|
await Tag.addNote(tag1.id, note1.id);
|
||||||
@ -155,8 +155,8 @@ describe('services_InteropService', function() {
|
|||||||
await service.import({ path: filePath });
|
await service.import({ path: filePath });
|
||||||
|
|
||||||
expect(await Tag.count()).toBe(1);
|
expect(await Tag.count()).toBe(1);
|
||||||
let tag2 = (await Tag.all())[0];
|
const tag2 = (await Tag.all())[0];
|
||||||
let note2 = (await Note.all())[0];
|
const note2 = (await Note.all())[0];
|
||||||
expect(tag1.id).not.toBe(tag2.id);
|
expect(tag1.id).not.toBe(tag2.id);
|
||||||
|
|
||||||
let fieldNames = Note.fieldNames();
|
let fieldNames = Note.fieldNames();
|
||||||
@ -180,12 +180,12 @@ describe('services_InteropService', function() {
|
|||||||
it('should export and import resources', asyncTest(async () => {
|
it('should export and import resources', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
let resourceIds = await Note.linkedResourceIds(note1.body);
|
let resourceIds = await Note.linkedResourceIds(note1.body);
|
||||||
let resource1 = await Resource.load(resourceIds[0]);
|
const resource1 = await Resource.load(resourceIds[0]);
|
||||||
|
|
||||||
await service.export({ path: filePath });
|
await service.export({ path: filePath });
|
||||||
|
|
||||||
@ -195,11 +195,11 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
expect(await Resource.count()).toBe(2);
|
expect(await Resource.count()).toBe(2);
|
||||||
|
|
||||||
let note2 = (await Note.all())[0];
|
const note2 = (await Note.all())[0];
|
||||||
expect(note2.body).not.toBe(note1.body);
|
expect(note2.body).not.toBe(note1.body);
|
||||||
resourceIds = await Note.linkedResourceIds(note2.body);
|
resourceIds = await Note.linkedResourceIds(note2.body);
|
||||||
expect(resourceIds.length).toBe(1);
|
expect(resourceIds.length).toBe(1);
|
||||||
let resource2 = await Resource.load(resourceIds[0]);
|
const resource2 = await Resource.load(resourceIds[0]);
|
||||||
expect(resource2.id).not.toBe(resource1.id);
|
expect(resource2.id).not.toBe(resource1.id);
|
||||||
|
|
||||||
let fieldNames = Note.fieldNames();
|
let fieldNames = Note.fieldNames();
|
||||||
@ -216,8 +216,8 @@ describe('services_InteropService', function() {
|
|||||||
it('should export and import single notes', asyncTest(async () => {
|
it('should export and import single notes', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
|
|
||||||
await service.export({ path: filePath, sourceNoteIds: [note1.id] });
|
await service.export({ path: filePath, sourceNoteIds: [note1.id] });
|
||||||
|
|
||||||
@ -229,15 +229,15 @@ describe('services_InteropService', function() {
|
|||||||
expect(await Note.count()).toBe(1);
|
expect(await Note.count()).toBe(1);
|
||||||
expect(await Folder.count()).toBe(1);
|
expect(await Folder.count()).toBe(1);
|
||||||
|
|
||||||
let folder2 = (await Folder.all())[0];
|
const folder2 = (await Folder.all())[0];
|
||||||
expect(folder2.title).toBe('test');
|
expect(folder2.title).toBe('test');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should export and import single folders', asyncTest(async () => {
|
it('should export and import single folders', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
|
|
||||||
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ describe('services_InteropService', function() {
|
|||||||
expect(await Note.count()).toBe(1);
|
expect(await Note.count()).toBe(1);
|
||||||
expect(await Folder.count()).toBe(1);
|
expect(await Folder.count()).toBe(1);
|
||||||
|
|
||||||
let folder2 = (await Folder.all())[0];
|
const folder2 = (await Folder.all())[0];
|
||||||
expect(folder2.title).toBe('folder1');
|
expect(folder2.title).toBe('folder1');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -257,11 +257,11 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let folder3 = await Folder.save({ title: 'folder3', parent_id: folder2.id });
|
const folder3 = await Folder.save({ title: 'folder3', parent_id: folder2.id });
|
||||||
let folder4 = await Folder.save({ title: 'folder4', parent_id: folder2.id });
|
const folder4 = await Folder.save({ title: 'folder4', parent_id: folder2.id });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder4.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder4.id });
|
||||||
|
|
||||||
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
||||||
|
|
||||||
@ -276,11 +276,11 @@ describe('services_InteropService', function() {
|
|||||||
expect(await Note.count()).toBe(1);
|
expect(await Note.count()).toBe(1);
|
||||||
expect(await Folder.count()).toBe(4);
|
expect(await Folder.count()).toBe(4);
|
||||||
|
|
||||||
let folder1_2 = await Folder.loadByTitle('folder1');
|
const folder1_2 = await Folder.loadByTitle('folder1');
|
||||||
let folder2_2 = await Folder.loadByTitle('folder2');
|
const folder2_2 = await Folder.loadByTitle('folder2');
|
||||||
let folder3_2 = await Folder.loadByTitle('folder3');
|
const folder3_2 = await Folder.loadByTitle('folder3');
|
||||||
let folder4_2 = await Folder.loadByTitle('folder4');
|
const folder4_2 = await Folder.loadByTitle('folder4');
|
||||||
let note1_2 = await Note.loadByTitle('ma note');
|
const note1_2 = await Note.loadByTitle('ma note');
|
||||||
|
|
||||||
expect(folder2_2.parent_id).toBe(folder1_2.id);
|
expect(folder2_2.parent_id).toBe(folder1_2.id);
|
||||||
expect(folder3_2.parent_id).toBe(folder2_2.id);
|
expect(folder3_2.parent_id).toBe(folder2_2.id);
|
||||||
@ -291,9 +291,9 @@ describe('services_InteropService', function() {
|
|||||||
it('should export and import links to notes', asyncTest(async () => {
|
it('should export and import links to notes', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const filePath = `${exportDir()}/test.jex`;
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma deuxième note', body: `Lien vers première note : ${Note.markdownTag(note1)}`, parent_id: folder1.id });
|
||||||
|
|
||||||
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
|
||||||
|
|
||||||
@ -306,15 +306,15 @@ describe('services_InteropService', function() {
|
|||||||
expect(await Note.count()).toBe(2);
|
expect(await Note.count()).toBe(2);
|
||||||
expect(await Folder.count()).toBe(1);
|
expect(await Folder.count()).toBe(1);
|
||||||
|
|
||||||
let note1_2 = await Note.loadByTitle('ma note');
|
const note1_2 = await Note.loadByTitle('ma note');
|
||||||
let note2_2 = await Note.loadByTitle('ma deuxième note');
|
const note2_2 = await Note.loadByTitle('ma deuxième note');
|
||||||
|
|
||||||
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
|
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should export into json format', asyncTest(async () => {
|
it('should export into json format', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
const filePath = exportDir();
|
const filePath = exportDir();
|
||||||
@ -325,8 +325,8 @@ describe('services_InteropService', function() {
|
|||||||
const items = [folder1, note1];
|
const items = [folder1, note1];
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
const jsonFile = `${filePath}/${items[i].id}.json`;
|
const jsonFile = `${filePath}/${items[i].id}.json`;
|
||||||
let json = await fs.readFile(jsonFile, 'utf-8');
|
const json = await fs.readFile(jsonFile, 'utf-8');
|
||||||
let obj = JSON.parse(json);
|
const obj = JSON.parse(json);
|
||||||
expect(obj.id).toBe(items[i].id);
|
expect(obj.id).toBe(items[i].id);
|
||||||
expect(obj.type_).toBe(items[i].type_);
|
expect(obj.type_).toBe(items[i].type_);
|
||||||
expect(obj.title).toBe(items[i].title);
|
expect(obj.title).toBe(items[i].title);
|
||||||
@ -336,7 +336,7 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
it('should export selected notes in md format', asyncTest(async () => {
|
it('should export selected notes in md format', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note11 = await Note.save({ title: 'title note11', parent_id: folder1.id });
|
let note11 = await Note.save({ title: 'title note11', parent_id: folder1.id });
|
||||||
note11 = await Note.load(note11.id);
|
note11 = await Note.load(note11.id);
|
||||||
let note12 = await Note.save({ title: 'title note12', parent_id: folder1.id });
|
let note12 = await Note.save({ title: 'title note12', parent_id: folder1.id });
|
||||||
@ -365,15 +365,15 @@ describe('services_InteropService', function() {
|
|||||||
|
|
||||||
it('should export MD with unicode filenames', asyncTest(async () => {
|
it('should export MD with unicode filenames', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'ジョプリン' });
|
const folder2 = await Folder.save({ title: 'ジョプリン' });
|
||||||
let note1 = await Note.save({ title: '生活', parent_id: folder1.id });
|
const note1 = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: '生活', parent_id: folder1.id });
|
const note2 = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||||
let note2b = await Note.save({ title: '生活', parent_id: folder1.id });
|
const note2b = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||||
let note3 = await Note.save({ title: '', parent_id: folder1.id });
|
const note3 = await Note.save({ title: '', parent_id: folder1.id });
|
||||||
let note4 = await Note.save({ title: '', parent_id: folder1.id });
|
const note4 = await Note.save({ title: '', parent_id: folder1.id });
|
||||||
let note5 = await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id });
|
const note5 = await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id });
|
||||||
let note6 = await Note.save({ title: 'ジョプリン', parent_id: folder2.id });
|
const note6 = await Note.save({ title: 'ジョプリン', parent_id: folder2.id });
|
||||||
|
|
||||||
const outDir = exportDir();
|
const outDir = exportDir();
|
||||||
|
|
||||||
|
@ -49,9 +49,9 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'note2', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||||
@ -59,7 +59,7 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
|
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2' });
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
let note3 = await Note.save({ title: 'note3', parent_id: folder2.id });
|
let note3 = await Note.save({ title: 'note3', parent_id: folder2.id });
|
||||||
await shim.attachFileToNote(note3, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note3, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note3 = await Note.load(note3.id);
|
note3 = await Note.load(note3.id);
|
||||||
@ -91,9 +91,9 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
let note1_2 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
const note1_2 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1_2);
|
queueExportItem(BaseModel.TYPE_NOTE, note1_2);
|
||||||
@ -118,8 +118,8 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
|
|
||||||
@ -145,23 +145,23 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
|
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note1.body))[0]);
|
||||||
let resource1 = await Resource.load(itemsToExport[2].itemOrId);
|
const resource1 = await Resource.load(itemsToExport[2].itemOrId);
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
||||||
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note2 = await Note.load(note2.id);
|
note2 = await Note.load(note2.id);
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note2.body))[0]);
|
queueExportItem(BaseModel.TYPE_RESOURCE, (await Note.linkedResourceIds(note2.body))[0]);
|
||||||
let resource2 = await Resource.load(itemsToExport[5].itemOrId);
|
const resource2 = await Resource.load(itemsToExport[5].itemOrId);
|
||||||
|
|
||||||
await exporter.processResource(resource1, Resource.fullPath(resource1));
|
await exporter.processResource(resource1, Resource.fullPath(resource1));
|
||||||
await exporter.processResource(resource2, Resource.fullPath(resource2));
|
await exporter.processResource(resource2, Resource.fullPath(resource2));
|
||||||
@ -182,13 +182,13 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
const note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
|
|
||||||
let folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id });
|
const folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
|
||||||
|
|
||||||
await exporter.processItem(Folder, folder2);
|
await exporter.processItem(Folder, folder2);
|
||||||
@ -213,18 +213,18 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
const note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
|
|
||||||
let folder3 = await Folder.save({ title: 'folder3' });
|
const folder3 = await Folder.save({ title: 'folder3' });
|
||||||
let note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
|
const note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
|
||||||
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
|
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note3);
|
queueExportItem(BaseModel.TYPE_NOTE, note3);
|
||||||
|
|
||||||
@ -250,24 +250,24 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note1 = await Note.load(note1.id);
|
note1 = await Note.load(note1.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
let resource1 = await Resource.load((await Note.linkedResourceIds(note1.body))[0]);
|
const resource1 = await Resource.load((await Note.linkedResourceIds(note1.body))[0]);
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
||||||
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
note2 = await Note.load(note2.id);
|
note2 = await Note.load(note2.id);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
let resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]);
|
const resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]);
|
||||||
|
|
||||||
await exporter.processItem(Folder, folder1);
|
await exporter.processItem(Folder, folder1);
|
||||||
await exporter.processItem(Folder, folder2);
|
await exporter.processItem(Folder, folder2);
|
||||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||||
let context = {
|
const context = {
|
||||||
resourcePaths: {},
|
resourcePaths: {},
|
||||||
};
|
};
|
||||||
context.resourcePaths[resource1.id] = 'resource1.jpg';
|
context.resourcePaths[resource1.id] = 'resource1.jpg';
|
||||||
@ -276,8 +276,8 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
await exporter.processItem(Note, note1);
|
await exporter.processItem(Note, note1);
|
||||||
await exporter.processItem(Note, note2);
|
await exporter.processItem(Note, note2);
|
||||||
|
|
||||||
let note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
||||||
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||||
|
|
||||||
expect(note1_body).toContain('](../_resources/resource1.jpg)', 'Resource id should be replaced with a relative path.');
|
expect(note1_body).toContain('](../_resources/resource1.jpg)', 'Resource id should be replaced with a relative path.');
|
||||||
expect(note2_body).toContain('](../../_resources/resource2.jpg)', 'Resource id should be replaced with a relative path.');
|
expect(note2_body).toContain('](../../_resources/resource2.jpg)', 'Resource id should be replaced with a relative path.');
|
||||||
@ -301,13 +301,13 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
return await Note.load(note.id);
|
return await Note.load(note.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
|
|
||||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
|
||||||
|
|
||||||
let folder3 = await Folder.save({ title: 'folder3' });
|
const folder3 = await Folder.save({ title: 'folder3' });
|
||||||
let note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
|
let note3 = await Note.save({ title: 'note3', parent_id: folder3.id });
|
||||||
|
|
||||||
note1 = await changeNoteBodyAndReload(note1, `# Some text \n\n [A link to note3](:/${note3.id})`);
|
note1 = await changeNoteBodyAndReload(note1, `# Some text \n\n [A link to note3](:/${note3.id})`);
|
||||||
@ -325,9 +325,9 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
await exporter.processItem(Note, note2);
|
await exporter.processItem(Note, note2);
|
||||||
await exporter.processItem(Note, note3);
|
await exporter.processItem(Note, note3);
|
||||||
|
|
||||||
let note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
||||||
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||||
let note3_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note3.id]}`);
|
const note3_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note3.id]}`);
|
||||||
|
|
||||||
expect(note1_body).toContain('](../folder3/note3.md)', 'Note id should be replaced with a relative path.');
|
expect(note1_body).toContain('](../folder3/note3.md)', 'Note id should be replaced with a relative path.');
|
||||||
expect(note2_body).toContain('](../../folder3/note3.md)', 'Resource id should be replaced with a relative path.');
|
expect(note2_body).toContain('](../../folder3/note3.md)', 'Resource id should be replaced with a relative path.');
|
||||||
@ -347,9 +347,9 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder with space1' });
|
const folder1 = await Folder.save({ title: 'folder with space1' });
|
||||||
let note1 = await Note.save({ title: 'note1 name with space', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'note1 name with space', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'note2', parent_id: folder1.id, body: `[link](:/${note1.id})` });
|
const note2 = await Note.save({ title: 'note2', parent_id: folder1.id, body: `[link](:/${note1.id})` });
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ describe('services_InteropService_Exporter_Md', function() {
|
|||||||
await exporter.processItem(Note, note1);
|
await exporter.processItem(Note, note1);
|
||||||
await exporter.processItem(Note, note2);
|
await exporter.processItem(Note, note2);
|
||||||
|
|
||||||
let note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||||
expect(note2_body).toContain('[link](../folder%20with%20space1/note1%20name%20with%20space.md)', 'Whitespace in URL should be encoded');
|
expect(note2_body).toContain('[link](../folder%20with%20space1/note1%20name%20with%20space.md)', 'Whitespace in URL should be encoded');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -48,10 +48,10 @@ describe('services_ResourceService', function() {
|
|||||||
it('should delete orphaned resources', asyncTest(async () => {
|
it('should delete orphaned resources', asyncTest(async () => {
|
||||||
const service = new ResourceService();
|
const service = new ResourceService();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
const resourcePath = Resource.fullPath(resource1);
|
const resourcePath = Resource.fullPath(resource1);
|
||||||
|
|
||||||
await service.indexNoteResources();
|
await service.indexNoteResources();
|
||||||
@ -79,11 +79,11 @@ describe('services_ResourceService', function() {
|
|||||||
it('should not delete resource if still associated with at least one note', asyncTest(async () => {
|
it('should not delete resource if still associated with at least one note', asyncTest(async () => {
|
||||||
const service = new ResourceService();
|
const service = new ResourceService();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'ma deuxième note', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma deuxième note', parent_id: folder1.id });
|
||||||
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
|
|
||||||
await service.indexNoteResources();
|
await service.indexNoteResources();
|
||||||
|
|
||||||
@ -113,10 +113,10 @@ describe('services_ResourceService', function() {
|
|||||||
it('should not delete resource if it is used in an IMG tag', asyncTest(async () => {
|
it('should not delete resource if it is used in an IMG tag', asyncTest(async () => {
|
||||||
const service = new ResourceService();
|
const service = new ResourceService();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
|
|
||||||
await service.indexNoteResources();
|
await service.indexNoteResources();
|
||||||
|
|
||||||
@ -132,10 +132,10 @@ describe('services_ResourceService', function() {
|
|||||||
it('should not process twice the same change', asyncTest(async () => {
|
it('should not process twice the same change', asyncTest(async () => {
|
||||||
const service = new ResourceService();
|
const service = new ResourceService();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
|
|
||||||
await service.indexNoteResources();
|
await service.indexNoteResources();
|
||||||
|
|
||||||
@ -169,8 +169,8 @@ describe('services_ResourceService', function() {
|
|||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
await encryptionService().enableEncryption(masterKey, '123456');
|
await encryptionService().enableEncryption(masterKey, '123456');
|
||||||
await encryptionService().loadMasterKeysFromSettings();
|
await encryptionService().loadMasterKeysFromSettings();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); // R1
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); // R1
|
||||||
await resourceService().indexNoteResources();
|
await resourceService().indexNoteResources();
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
@ -199,7 +199,7 @@ describe('services_ResourceService', function() {
|
|||||||
it('should double-check if the resource is still linked before deleting it', asyncTest(async () => {
|
it('should double-check if the resource is still linked before deleting it', asyncTest(async () => {
|
||||||
SearchEngine.instance().setDb(db()); // /!\ Note that we use the global search engine here, which we shouldn't but will work for now
|
SearchEngine.instance().setDb(db()); // /!\ Note that we use the global search engine here, which we shouldn't but will work for now
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
await resourceService().indexNoteResources();
|
await resourceService().indexNoteResources();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
|
/* eslint prefer-const: 0*/
|
||||||
|
|
||||||
require('app-module-path').addPath(__dirname);
|
require('app-module-path').addPath(__dirname);
|
||||||
|
|
||||||
|
@ -37,26 +37,26 @@ describe('services_rest_Api', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get folders', asyncTest(async () => {
|
it('should get folders', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const response = await api.route('GET', 'folders');
|
const response = await api.route('GET', 'folders');
|
||||||
expect(response.length).toBe(1);
|
expect(response.length).toBe(1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should update folders', asyncTest(async () => {
|
it('should update folders', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({
|
const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({
|
||||||
title: 'modifié',
|
title: 'modifié',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let f1b = await Folder.load(f1.id);
|
const f1b = await Folder.load(f1.id);
|
||||||
expect(f1b.title).toBe('modifié');
|
expect(f1b.title).toBe('modifié');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete folders', asyncTest(async () => {
|
it('should delete folders', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
await api.route('DELETE', `folders/${f1.id}`);
|
await api.route('DELETE', `folders/${f1.id}`);
|
||||||
|
|
||||||
let f1b = await Folder.load(f1.id);
|
const f1b = await Folder.load(f1.id);
|
||||||
expect(!f1b).toBe(true);
|
expect(!f1b).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -67,13 +67,13 @@ describe('services_rest_Api', function() {
|
|||||||
|
|
||||||
expect(!!response.id).toBe(true);
|
expect(!!response.id).toBe(true);
|
||||||
|
|
||||||
let f = await Folder.all();
|
const f = await Folder.all();
|
||||||
expect(f.length).toBe(1);
|
expect(f.length).toBe(1);
|
||||||
expect(f[0].title).toBe('from api');
|
expect(f[0].title).toBe('from api');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get one folder', asyncTest(async () => {
|
it('should get one folder', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const response = await api.route('GET', `folders/${f1.id}`);
|
const response = await api.route('GET', `folders/${f1.id}`);
|
||||||
expect(response.id).toBe(f1.id);
|
expect(response.id).toBe(f1.id);
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ describe('services_rest_Api', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should get the folder notes', asyncTest(async () => {
|
it('should get the folder notes', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'mon carnet' });
|
const f1 = await Folder.save({ title: 'mon carnet' });
|
||||||
const response2 = await api.route('GET', `folders/${f1.id}/notes`);
|
const response2 = await api.route('GET', `folders/${f1.id}/notes`);
|
||||||
expect(response2.length).toBe(0);
|
expect(response2.length).toBe(0);
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ process.on('unhandledRejection', (reason, p) => {
|
|||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000 + 30000; // The first test is slow because the database needs to be built
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000 + 30000; // The first test is slow because the database needs to be built
|
||||||
|
|
||||||
async function allNotesFolders() {
|
async function allNotesFolders() {
|
||||||
let folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
return folders.concat(notes);
|
return folders.concat(notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,9 +66,9 @@ async function localNotesFoldersSameAsRemote(locals, expect) {
|
|||||||
expect(locals.length).toBe(nf.length);
|
expect(locals.length).toBe(nf.length);
|
||||||
|
|
||||||
for (let i = 0; i < locals.length; i++) {
|
for (let i = 0; i < locals.length; i++) {
|
||||||
let dbItem = locals[i];
|
const dbItem = locals[i];
|
||||||
let path = BaseItem.systemPath(dbItem);
|
const path = BaseItem.systemPath(dbItem);
|
||||||
let remote = await fileApi().stat(path);
|
const remote = await fileApi().stat(path);
|
||||||
|
|
||||||
expect(!!remote).toBe(true);
|
expect(!!remote).toBe(true);
|
||||||
if (!remote) continue;
|
if (!remote) continue;
|
||||||
@ -101,10 +101,10 @@ describe('synchronizer', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create remote items', asyncTest(async () => {
|
it('should create remote items', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder1' });
|
const folder = await Folder.save({ title: 'folder1' });
|
||||||
await Note.save({ title: 'un', parent_id: folder.id });
|
await Note.save({ title: 'un', parent_id: folder.id });
|
||||||
|
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -112,20 +112,20 @@ describe('synchronizer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should update remote items', asyncTest(async () => {
|
it('should update remote items', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder1' });
|
const folder = await Folder.save({ title: 'folder1' });
|
||||||
let note = await Note.save({ title: 'un', parent_id: folder.id });
|
const note = await Note.save({ title: 'un', parent_id: folder.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await Note.save({ title: 'un UPDATE', id: note.id });
|
await Note.save({ title: 'un UPDATE', id: note.id });
|
||||||
|
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await localNotesFoldersSameAsRemote(all, expect);
|
await localNotesFoldersSameAsRemote(all, expect);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should create local items', asyncTest(async () => {
|
it('should create local items', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder1' });
|
const folder = await Folder.save({ title: 'folder1' });
|
||||||
await Note.save({ title: 'un', parent_id: folder.id });
|
await Note.save({ title: 'un', parent_id: folder.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -133,14 +133,14 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
|
|
||||||
await localNotesFoldersSameAsRemote(all, expect);
|
await localNotesFoldersSameAsRemote(all, expect);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should update local items', asyncTest(async () => {
|
it('should update local items', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -160,14 +160,14 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
|
|
||||||
await localNotesFoldersSameAsRemote(all, expect);
|
await localNotesFoldersSameAsRemote(all, expect);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should resolve note conflicts', asyncTest(async () => {
|
it('should resolve note conflicts', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -186,29 +186,29 @@ describe('synchronizer', function() {
|
|||||||
await Note.save(note2conf);
|
await Note.save(note2conf);
|
||||||
note2conf = await Note.load(note1.id);
|
note2conf = await Note.load(note1.id);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let conflictedNotes = await Note.conflictedNotes();
|
const conflictedNotes = await Note.conflictedNotes();
|
||||||
expect(conflictedNotes.length).toBe(1);
|
expect(conflictedNotes.length).toBe(1);
|
||||||
|
|
||||||
// Other than the id (since the conflicted note is a duplicate), and the is_conflict property
|
// Other than the id (since the conflicted note is a duplicate), and the is_conflict property
|
||||||
// the conflicted and original note must be the same in every way, to make sure no data has been lost.
|
// the conflicted and original note must be the same in every way, to make sure no data has been lost.
|
||||||
let conflictedNote = conflictedNotes[0];
|
const conflictedNote = conflictedNotes[0];
|
||||||
expect(conflictedNote.id == note2conf.id).toBe(false);
|
expect(conflictedNote.id == note2conf.id).toBe(false);
|
||||||
for (let n in conflictedNote) {
|
for (const n in conflictedNote) {
|
||||||
if (!conflictedNote.hasOwnProperty(n)) continue;
|
if (!conflictedNote.hasOwnProperty(n)) continue;
|
||||||
if (n == 'id' || n == 'is_conflict') continue;
|
if (n == 'id' || n == 'is_conflict') continue;
|
||||||
expect(conflictedNote[n]).toBe(note2conf[n], `Property: ${n}`);
|
expect(conflictedNote[n]).toBe(note2conf[n], `Property: ${n}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let noteUpdatedFromRemote = await Note.load(note1.id);
|
const noteUpdatedFromRemote = await Note.load(note1.id);
|
||||||
for (let n in noteUpdatedFromRemote) {
|
for (const n in noteUpdatedFromRemote) {
|
||||||
if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue;
|
if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue;
|
||||||
expect(noteUpdatedFromRemote[n]).toBe(note2[n], `Property: ${n}`);
|
expect(noteUpdatedFromRemote[n]).toBe(note2[n], `Property: ${n}`);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should resolve folders conflicts', asyncTest(async () => {
|
it('should resolve folders conflicts', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2); // ----------------------------------
|
await switchClient(2); // ----------------------------------
|
||||||
@ -235,13 +235,13 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let folder1_final = await Folder.load(folder1.id);
|
const folder1_final = await Folder.load(folder1.id);
|
||||||
expect(folder1_final.title).toBe(folder1_modRemote.title);
|
expect(folder1_final.title).toBe(folder1_modRemote.title);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete remote notes', asyncTest(async () => {
|
it('should delete remote notes', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -258,13 +258,13 @@ describe('synchronizer', function() {
|
|||||||
expect(remotes.length).toBe(1);
|
expect(remotes.length).toBe(1);
|
||||||
expect(remotes[0].id).toBe(folder1.id);
|
expect(remotes[0].id).toBe(folder1.id);
|
||||||
|
|
||||||
let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
const deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
expect(deletedItems.length).toBe(0);
|
expect(deletedItems.length).toBe(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not created deleted_items entries for items deleted via sync', asyncTest(async () => {
|
it('should not created deleted_items entries for items deleted via sync', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -276,7 +276,7 @@ describe('synchronizer', function() {
|
|||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
const deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
expect(deletedItems.length).toBe(0);
|
expect(deletedItems.length).toBe(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -285,9 +285,9 @@ describe('synchronizer', function() {
|
|||||||
// property of the basicDelta() function is cleared properly at the end of a sync operation. If it is not cleared
|
// property of the basicDelta() function is cleared properly at the end of a sync operation. If it is not cleared
|
||||||
// it means items will no longer be deleted locally via sync.
|
// it means items will no longer be deleted locally via sync.
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
|
||||||
let context1 = await synchronizer().start();
|
let context1 = await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -299,17 +299,17 @@ describe('synchronizer', function() {
|
|||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
context1 = await synchronizer().start({ context: context1 });
|
context1 = await synchronizer().start({ context: context1 });
|
||||||
let items = await allNotesFolders();
|
const items = await allNotesFolders();
|
||||||
expect(items.length).toBe(2);
|
expect(items.length).toBe(2);
|
||||||
let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
const deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
expect(deletedItems.length).toBe(0);
|
expect(deletedItems.length).toBe(0);
|
||||||
await Note.delete(note2.id);
|
await Note.delete(note2.id);
|
||||||
context1 = await synchronizer().start({ context: context1 });
|
context1 = await synchronizer().start({ context: context1 });
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete remote folder', asyncTest(async () => {
|
it('should delete remote folder', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'folder2' });
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -322,30 +322,30 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
await localNotesFoldersSameAsRemote(all, expect);
|
await localNotesFoldersSameAsRemote(all, expect);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should delete local folder', asyncTest(async () => {
|
it('should delete local folder', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'folder2' });
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
let context1 = await synchronizer().start();
|
const context1 = await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
let context2 = await synchronizer().start();
|
const context2 = await synchronizer().start();
|
||||||
await Folder.delete(folder2.id);
|
await Folder.delete(folder2.id);
|
||||||
await synchronizer().start({ context: context2 });
|
await synchronizer().start({ context: context2 });
|
||||||
|
|
||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
await synchronizer().start({ context: context1 });
|
await synchronizer().start({ context: context1 });
|
||||||
let items = await allNotesFolders();
|
const items = await allNotesFolders();
|
||||||
await localNotesFoldersSameAsRemote(items, expect);
|
await localNotesFoldersSameAsRemote(items, expect);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', asyncTest(async () => {
|
it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -356,17 +356,17 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
let note = await Note.save({ title: 'note1', parent_id: folder1.id });
|
const note = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let items = await allNotesFolders();
|
const items = await allNotesFolders();
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
expect(items[0].title).toBe('note1');
|
expect(items[0].title).toBe('note1');
|
||||||
expect(items[0].is_conflict).toBe(1);
|
expect(items[0].is_conflict).toBe(1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should resolve conflict if note has been deleted remotely and locally', asyncTest(async () => {
|
it('should resolve conflict if note has been deleted remotely and locally', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder' });
|
const folder = await Folder.save({ title: 'folder' });
|
||||||
let note = await Note.save({ title: 'note', parent_id: folder.title });
|
const note = await Note.save({ title: 'note', parent_id: folder.title });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -380,7 +380,7 @@ describe('synchronizer', function() {
|
|||||||
await Note.delete(note.id);
|
await Note.delete(note.id);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let items = await allNotesFolders();
|
const items = await allNotesFolders();
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
expect(items[0].title).toBe('folder');
|
expect(items[0].title).toBe('folder');
|
||||||
|
|
||||||
@ -391,8 +391,8 @@ describe('synchronizer', function() {
|
|||||||
// If client1 and 2 have two folders, client 1 deletes item 1 and client
|
// If client1 and 2 have two folders, client 1 deletes item 1 and client
|
||||||
// 2 deletes item 2, they should both end up with no items after sync.
|
// 2 deletes item 2, they should both end up with no items after sync.
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'folder2' });
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -413,21 +413,21 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let items2 = await allNotesFolders();
|
const items2 = await allNotesFolders();
|
||||||
|
|
||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let items1 = await allNotesFolders();
|
const items1 = await allNotesFolders();
|
||||||
|
|
||||||
expect(items1.length).toBe(0);
|
expect(items1.length).toBe(0);
|
||||||
expect(items1.length).toBe(items2.length);
|
expect(items1.length).toBe(items2.length);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should handle conflict when remote note is deleted then local note is modified', asyncTest(async () => {
|
it('should handle conflict when remote note is deleted then local note is modified', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -442,25 +442,25 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
let newTitle = 'Modified after having been deleted';
|
const newTitle = 'Modified after having been deleted';
|
||||||
await Note.save({ id: note1.id, title: newTitle });
|
await Note.save({ id: note1.id, title: newTitle });
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let conflictedNotes = await Note.conflictedNotes();
|
const conflictedNotes = await Note.conflictedNotes();
|
||||||
|
|
||||||
expect(conflictedNotes.length).toBe(1);
|
expect(conflictedNotes.length).toBe(1);
|
||||||
expect(conflictedNotes[0].title).toBe(newTitle);
|
expect(conflictedNotes[0].title).toBe(newTitle);
|
||||||
|
|
||||||
let unconflictedNotes = await Note.unconflictedNotes();
|
const unconflictedNotes = await Note.unconflictedNotes();
|
||||||
|
|
||||||
expect(unconflictedNotes.length).toBe(0);
|
expect(unconflictedNotes.length).toBe(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should handle conflict when remote folder is deleted then local folder is renamed', asyncTest(async () => {
|
it('should handle conflict when remote folder is deleted then local folder is renamed', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let folder2 = await Folder.save({ title: 'folder2' });
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -477,18 +477,18 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
let newTitle = 'Modified after having been deleted';
|
const newTitle = 'Modified after having been deleted';
|
||||||
await Folder.save({ id: folder1.id, title: newTitle });
|
await Folder.save({ id: folder1.id, title: newTitle });
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let items = await allNotesFolders();
|
const items = await allNotesFolders();
|
||||||
|
|
||||||
expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should allow duplicate folder titles', asyncTest(async () => {
|
it('should allow duplicate folder titles', asyncTest(async () => {
|
||||||
let localF1 = await Folder.save({ title: 'folder' });
|
const localF1 = await Folder.save({ title: 'folder' });
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
@ -501,7 +501,7 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let localF2 = await Folder.load(remoteF2.id);
|
const localF2 = await Folder.load(remoteF2.id);
|
||||||
|
|
||||||
expect(localF2.title == remoteF2.title).toBe(true);
|
expect(localF2.title == remoteF2.title).toBe(true);
|
||||||
|
|
||||||
@ -528,10 +528,10 @@ describe('synchronizer', function() {
|
|||||||
masterKey = await loadEncryptionMasterKey();
|
masterKey = await loadEncryptionMasterKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
let f1 = await Folder.save({ title: 'folder' });
|
const f1 = await Folder.save({ title: 'folder' });
|
||||||
let n1 = await Note.save({ title: 'mynote' });
|
const n1 = await Note.save({ title: 'mynote' });
|
||||||
let n2 = await Note.save({ title: 'mynote2' });
|
const n2 = await Note.save({ title: 'mynote2' });
|
||||||
let tag = await Tag.save({ title: 'mytag' });
|
const tag = await Tag.save({ title: 'mytag' });
|
||||||
let context1 = await synchronizer().start();
|
let context1 = await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -540,10 +540,10 @@ describe('synchronizer', function() {
|
|||||||
if (withEncryption) {
|
if (withEncryption) {
|
||||||
const masterKey_2 = await MasterKey.load(masterKey.id);
|
const masterKey_2 = await MasterKey.load(masterKey.id);
|
||||||
await encryptionService().loadMasterKey_(masterKey_2, '123456', true);
|
await encryptionService().loadMasterKey_(masterKey_2, '123456', true);
|
||||||
let t = await Tag.load(tag.id);
|
const t = await Tag.load(tag.id);
|
||||||
await Tag.decrypt(t);
|
await Tag.decrypt(t);
|
||||||
}
|
}
|
||||||
let remoteTag = await Tag.loadByTitle(tag.title);
|
const remoteTag = await Tag.loadByTitle(tag.title);
|
||||||
expect(!!remoteTag).toBe(true);
|
expect(!!remoteTag).toBe(true);
|
||||||
expect(remoteTag.id).toBe(tag.id);
|
expect(remoteTag.id).toBe(tag.id);
|
||||||
await Tag.addNote(remoteTag.id, n1.id);
|
await Tag.addNote(remoteTag.id, n1.id);
|
||||||
@ -579,22 +579,22 @@ describe('synchronizer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not sync notes with conflicts', asyncTest(async () => {
|
it('should not sync notes with conflicts', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'folder' });
|
const f1 = await Folder.save({ title: 'folder' });
|
||||||
let n1 = await Note.save({ title: 'mynote', parent_id: f1.id, is_conflict: 1 });
|
const n1 = await Note.save({ title: 'mynote', parent_id: f1.id, is_conflict: 1 });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
let folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
expect(notes.length).toBe(0);
|
expect(notes.length).toBe(0);
|
||||||
expect(folders.length).toBe(1);
|
expect(folders.length).toBe(1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should not try to delete on remote conflicted notes that have been deleted', asyncTest(async () => {
|
it('should not try to delete on remote conflicted notes that have been deleted', asyncTest(async () => {
|
||||||
let f1 = await Folder.save({ title: 'folder' });
|
const f1 = await Folder.save({ title: 'folder' });
|
||||||
let n1 = await Note.save({ title: 'mynote', parent_id: f1.id });
|
const n1 = await Note.save({ title: 'mynote', parent_id: f1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -613,8 +613,8 @@ describe('synchronizer', function() {
|
|||||||
await loadEncryptionMasterKey();
|
await loadEncryptionMasterKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -625,7 +625,7 @@ describe('synchronizer', function() {
|
|||||||
await decryptionWorker().start();
|
await decryptionWorker().start();
|
||||||
}
|
}
|
||||||
let note2 = await Note.load(note1.id);
|
let note2 = await Note.load(note1.id);
|
||||||
note2.todo_completed = time.unixMs()-1;
|
note2.todo_completed = time.unixMs() - 1;
|
||||||
await Note.save(note2);
|
await Note.save(note2);
|
||||||
note2 = await Note.load(note2.id);
|
note2 = await Note.load(note2.id);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
@ -646,10 +646,10 @@ describe('synchronizer', function() {
|
|||||||
// but in practice it doesn't matter, we can just take the date when the
|
// but in practice it doesn't matter, we can just take the date when the
|
||||||
// todo was marked as "done" the first time.
|
// todo was marked as "done" the first time.
|
||||||
|
|
||||||
let conflictedNotes = await Note.conflictedNotes();
|
const conflictedNotes = await Note.conflictedNotes();
|
||||||
expect(conflictedNotes.length).toBe(0);
|
expect(conflictedNotes.length).toBe(0);
|
||||||
|
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
expect(notes.length).toBe(1);
|
expect(notes.length).toBe(1);
|
||||||
expect(notes[0].id).toBe(note1.id);
|
expect(notes[0].id).toBe(note1.id);
|
||||||
expect(notes[0].todo_completed).toBe(note2.todo_completed);
|
expect(notes[0].todo_completed).toBe(note2.todo_completed);
|
||||||
@ -658,10 +658,10 @@ describe('synchronizer', function() {
|
|||||||
// smart conflict resolving since we don't know the content, so in that
|
// smart conflict resolving since we don't know the content, so in that
|
||||||
// case it's handled as a regular conflict.
|
// case it's handled as a regular conflict.
|
||||||
|
|
||||||
let conflictedNotes = await Note.conflictedNotes();
|
const conflictedNotes = await Note.conflictedNotes();
|
||||||
expect(conflictedNotes.length).toBe(1);
|
expect(conflictedNotes.length).toBe(1);
|
||||||
|
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
expect(notes.length).toBe(2);
|
expect(notes.length).toBe(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -675,14 +675,14 @@ describe('synchronizer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('items should be downloaded again when user cancels in the middle of delta operation', asyncTest(async () => {
|
it('items should be downloaded again when user cancels in the middle of delta operation', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
synchronizer().testingHooks_ = ['cancelDeltaLoop2'];
|
synchronizer().testingHooks_ = ['cancelDeltaLoop2'];
|
||||||
let context = await synchronizer().start();
|
const context = await synchronizer().start();
|
||||||
let notes = await Note.all();
|
let notes = await Note.all();
|
||||||
expect(notes.length).toBe(0);
|
expect(notes.length).toBe(0);
|
||||||
|
|
||||||
@ -693,8 +693,8 @@ describe('synchronizer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should skip items that cannot be synced', asyncTest(async () => {
|
it('should skip items that cannot be synced', asyncTest(async () => {
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
||||||
const noteId = note1.id;
|
const noteId = note1.id;
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let disabledItems = await BaseItem.syncDisabledItems(syncTargetId());
|
let disabledItems = await BaseItem.syncDisabledItems(syncTargetId());
|
||||||
@ -708,7 +708,7 @@ describe('synchronizer', function() {
|
|||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let notes = await Note.all();
|
const notes = await Note.all();
|
||||||
expect(notes.length).toBe(1);
|
expect(notes.length).toBe(1);
|
||||||
expect(notes[0].title).toBe('un');
|
expect(notes[0].title).toBe('un');
|
||||||
|
|
||||||
@ -721,7 +721,7 @@ describe('synchronizer', function() {
|
|||||||
it('notes and folders should get encrypted when encryption is enabled', asyncTest(async () => {
|
it('notes and folders should get encrypted when encryption is enabled', asyncTest(async () => {
|
||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', body: 'to be encrypted', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'un', body: 'to be encrypted', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
// After synchronisation, remote items should be encrypted but local ones remain plain text
|
// After synchronisation, remote items should be encrypted but local ones remain plain text
|
||||||
@ -733,7 +733,7 @@ describe('synchronizer', function() {
|
|||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let folder1_2 = await Folder.load(folder1.id);
|
let folder1_2 = await Folder.load(folder1.id);
|
||||||
let note1_2 = await Note.load(note1.id);
|
let note1_2 = await Note.load(note1.id);
|
||||||
let masterKey_2 = await MasterKey.load(masterKey.id);
|
const masterKey_2 = await MasterKey.load(masterKey.id);
|
||||||
// On this side however it should be received encrypted
|
// On this side however it should be received encrypted
|
||||||
expect(!note1_2.title).toBe(true);
|
expect(!note1_2.title).toBe(true);
|
||||||
expect(!folder1_2.title).toBe(true);
|
expect(!folder1_2.title).toBe(true);
|
||||||
@ -820,7 +820,7 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
it('should encrypt existing notes too when enabling E2EE', asyncTest(async () => {
|
it('should encrypt existing notes too when enabling E2EE', asyncTest(async () => {
|
||||||
// First create a folder, without encryption enabled, and sync it
|
// First create a folder, without encryption enabled, and sync it
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let files = await fileApi().list();
|
let files = await fileApi().list();
|
||||||
let content = await fileApi().get(files.items[0].path);
|
let content = await fileApi().get(files.items[0].path);
|
||||||
@ -848,18 +848,18 @@ describe('synchronizer', function() {
|
|||||||
it('should sync resources', asyncTest(async () => {
|
it('should sync resources', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(500);
|
while (insideBeforeEach) await time.msleep(500);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
let resourcePath1 = Resource.fullPath(resource1);
|
const resourcePath1 = Resource.fullPath(resource1);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
expect((await remoteNotesFoldersResources()).length).toBe(3);
|
expect((await remoteNotesFoldersResources()).length).toBe(3);
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let allResources = await Resource.all();
|
const allResources = await Resource.all();
|
||||||
expect(allResources.length).toBe(1);
|
expect(allResources.length).toBe(1);
|
||||||
let resource1_2 = allResources[0];
|
let resource1_2 = allResources[0];
|
||||||
let ls = await Resource.localState(resource1_2);
|
let ls = await Resource.localState(resource1_2);
|
||||||
@ -874,18 +874,18 @@ describe('synchronizer', function() {
|
|||||||
ls = await Resource.localState(resource1_2);
|
ls = await Resource.localState(resource1_2);
|
||||||
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
|
||||||
|
|
||||||
let resourcePath1_2 = Resource.fullPath(resource1_2);
|
const resourcePath1_2 = Resource.fullPath(resource1_2);
|
||||||
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
|
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should handle resource download errors', asyncTest(async () => {
|
it('should handle resource download errors', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(500);
|
while (insideBeforeEach) await time.msleep(500);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
let resource1 = (await Resource.all())[0];
|
||||||
let resourcePath1 = Resource.fullPath(resource1);
|
const resourcePath1 = Resource.fullPath(resource1);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -902,7 +902,7 @@ describe('synchronizer', function() {
|
|||||||
await fetcher.waitForAllFinished();
|
await fetcher.waitForAllFinished();
|
||||||
|
|
||||||
resource1 = await Resource.load(resource1.id);
|
resource1 = await Resource.load(resource1.id);
|
||||||
let ls = await Resource.localState(resource1);
|
const ls = await Resource.localState(resource1);
|
||||||
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_ERROR);
|
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_ERROR);
|
||||||
expect(ls.fetch_error).toBe('did not work');
|
expect(ls.fetch_error).toBe('did not work');
|
||||||
}));
|
}));
|
||||||
@ -910,8 +910,8 @@ describe('synchronizer', function() {
|
|||||||
it('should set the resource file size if it is missing', asyncTest(async () => {
|
it('should set the resource file size if it is missing', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(500);
|
while (insideBeforeEach) await time.msleep(500);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -933,11 +933,11 @@ describe('synchronizer', function() {
|
|||||||
it('should delete resources', asyncTest(async () => {
|
it('should delete resources', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(500);
|
while (insideBeforeEach) await time.msleep(500);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
let resourcePath1 = Resource.fullPath(resource1);
|
const resourcePath1 = Resource.fullPath(resource1);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -945,7 +945,7 @@ describe('synchronizer', function() {
|
|||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let allResources = await Resource.all();
|
let allResources = await Resource.all();
|
||||||
expect(allResources.length).toBe(1);
|
expect(allResources.length).toBe(1);
|
||||||
let all = await fileApi().list();
|
const all = await fileApi().list();
|
||||||
expect((await remoteNotesFoldersResources()).length).toBe(3);
|
expect((await remoteNotesFoldersResources()).length).toBe(3);
|
||||||
await Resource.delete(resource1.id);
|
await Resource.delete(resource1.id);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
@ -967,11 +967,11 @@ describe('synchronizer', function() {
|
|||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
let resourcePath1 = Resource.fullPath(resource1);
|
const resourcePath1 = Resource.fullPath(resource1);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -986,7 +986,7 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
let resource1_2 = (await Resource.all())[0];
|
let resource1_2 = (await Resource.all())[0];
|
||||||
resource1_2 = await Resource.decrypt(resource1_2);
|
resource1_2 = await Resource.decrypt(resource1_2);
|
||||||
let resourcePath1_2 = Resource.fullPath(resource1_2);
|
const resourcePath1_2 = Resource.fullPath(resource1_2);
|
||||||
|
|
||||||
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
|
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
|
||||||
}));
|
}));
|
||||||
@ -995,7 +995,7 @@ describe('synchronizer', function() {
|
|||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let allEncrypted = await allSyncTargetItemsEncrypted();
|
let allEncrypted = await allSyncTargetItemsEncrypted();
|
||||||
@ -1016,7 +1016,7 @@ describe('synchronizer', function() {
|
|||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -1049,12 +1049,12 @@ describe('synchronizer', function() {
|
|||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
await Resource.setFileSizeOnly(resource1.id, -1);
|
await Resource.setFileSizeOnly(resource1.id, -1);
|
||||||
let resourcePath1 = Resource.fullPath(resource1);
|
const resourcePath1 = Resource.fullPath(resource1);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -1075,8 +1075,8 @@ describe('synchronizer', function() {
|
|||||||
it('should encrypt remote resources after encryption has been enabled', asyncTest(async () => {
|
it('should encrypt remote resources after encryption has been enabled', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(100);
|
while (insideBeforeEach) await time.msleep(100);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -1094,22 +1094,22 @@ describe('synchronizer', function() {
|
|||||||
it('should upload encrypted resource, but it should not mark the blob as encrypted locally', asyncTest(async () => {
|
it('should upload encrypted resource, but it should not mark the blob as encrypted locally', asyncTest(async () => {
|
||||||
while (insideBeforeEach) await time.msleep(100);
|
while (insideBeforeEach) await time.msleep(100);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||||
const masterKey = await loadEncryptionMasterKey();
|
const masterKey = await loadEncryptionMasterKey();
|
||||||
await encryptionService().enableEncryption(masterKey, '123456');
|
await encryptionService().enableEncryption(masterKey, '123456');
|
||||||
await encryptionService().loadMasterKeysFromSettings();
|
await encryptionService().loadMasterKeysFromSettings();
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let resource1 = (await Resource.all())[0];
|
const resource1 = (await Resource.all())[0];
|
||||||
expect(resource1.encryption_blob_encrypted).toBe(0);
|
expect(resource1.encryption_blob_encrypted).toBe(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should create remote items with UTF-8 content', asyncTest(async () => {
|
it('should create remote items with UTF-8 content', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'Fahrräder' });
|
const folder = await Folder.save({ title: 'Fahrräder' });
|
||||||
await Note.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id });
|
await Note.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id });
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -1117,8 +1117,8 @@ describe('synchronizer', function() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should update remote items but not pull remote changes', asyncTest(async () => {
|
it('should update remote items but not pull remote changes', asyncTest(async () => {
|
||||||
let folder = await Folder.save({ title: 'folder1' });
|
const folder = await Folder.save({ title: 'folder1' });
|
||||||
let note = await Note.save({ title: 'un', parent_id: folder.id });
|
const note = await Note.save({ title: 'un', parent_id: folder.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
@ -1131,13 +1131,13 @@ describe('synchronizer', function() {
|
|||||||
|
|
||||||
await Note.save({ title: 'un UPDATE', id: note.id });
|
await Note.save({ title: 'un UPDATE', id: note.id });
|
||||||
await synchronizer().start({ syncSteps: ['update_remote'] });
|
await synchronizer().start({ syncSteps: ['update_remote'] });
|
||||||
let all = await allNotesFolders();
|
const all = await allNotesFolders();
|
||||||
expect(all.length).toBe(2);
|
expect(all.length).toBe(2);
|
||||||
|
|
||||||
await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
let note2 = await Note.load(note.id);
|
const note2 = await Note.load(note.id);
|
||||||
expect(note2.title).toBe('un UPDATE');
|
expect(note2.title).toBe('un UPDATE');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -1544,8 +1544,8 @@ describe('synchronizer', function() {
|
|||||||
Setting.setValue('encryption.enabled', true);
|
Setting.setValue('encryption.enabled', true);
|
||||||
await loadEncryptionMasterKey();
|
await loadEncryptionMasterKey();
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
let note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'un', parent_id: folder1.id });
|
||||||
let note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
|
let note2 = await Note.save({ title: 'deux', parent_id: folder1.id });
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
@ -1570,12 +1570,12 @@ describe('synchronizer', function() {
|
|||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// The shared note should be decrypted
|
// The shared note should be decrypted
|
||||||
let note2_2 = await Note.load(note2.id);
|
const note2_2 = await Note.load(note2.id);
|
||||||
expect(note2_2.title).toBe('deux');
|
expect(note2_2.title).toBe('deux');
|
||||||
expect(note2_2.is_shared).toBe(1);
|
expect(note2_2.is_shared).toBe(1);
|
||||||
|
|
||||||
// The non-shared note should be encrypted
|
// The non-shared note should be encrypted
|
||||||
let note1_2 = await Note.load(note1.id);
|
const note1_2 = await Note.load(note1.id);
|
||||||
expect(note1_2.title).toBe('');
|
expect(note1_2.title).toBe('');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const { JoplinDatabase } = require('lib/joplin-database.js');
|
const { JoplinDatabase } = require('lib/joplin-database.js');
|
||||||
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
||||||
const { BaseApplication }= require('lib/BaseApplication.js');
|
const { BaseApplication } = require('lib/BaseApplication.js');
|
||||||
const BaseModel = require('lib/BaseModel.js');
|
const BaseModel = require('lib/BaseModel.js');
|
||||||
const Folder = require('lib/models/Folder.js');
|
const Folder = require('lib/models/Folder.js');
|
||||||
const Note = require('lib/models/Note.js');
|
const Note = require('lib/models/Note.js');
|
||||||
@ -41,13 +41,13 @@ const KvStore = require('lib/services/KvStore.js');
|
|||||||
const WebDavApi = require('lib/WebDavApi');
|
const WebDavApi = require('lib/WebDavApi');
|
||||||
const DropboxApi = require('lib/DropboxApi');
|
const DropboxApi = require('lib/DropboxApi');
|
||||||
|
|
||||||
let databases_ = [];
|
const databases_ = [];
|
||||||
let synchronizers_ = [];
|
const synchronizers_ = [];
|
||||||
let encryptionServices_ = [];
|
const encryptionServices_ = [];
|
||||||
let revisionServices_ = [];
|
const revisionServices_ = [];
|
||||||
let decryptionWorkers_ = [];
|
const decryptionWorkers_ = [];
|
||||||
let resourceServices_ = [];
|
const resourceServices_ = [];
|
||||||
let kvStores_ = [];
|
const kvStores_ = [];
|
||||||
let fileApi_ = null;
|
let fileApi_ = null;
|
||||||
let currentClient_ = 1;
|
let currentClient_ = 1;
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ function fileApi() {
|
|||||||
|
|
||||||
function objectsEqual(o1, o2) {
|
function objectsEqual(o1, o2) {
|
||||||
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) return false;
|
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) return false;
|
||||||
for (let n in o1) {
|
for (const n in o1) {
|
||||||
if (!o1.hasOwnProperty(n)) continue;
|
if (!o1.hasOwnProperty(n)) continue;
|
||||||
if (o1[n] !== o2[n]) return false;
|
if (o1[n] !== o2[n]) return false;
|
||||||
}
|
}
|
||||||
@ -427,7 +427,7 @@ function sortedIds(a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function at(a, indexes) {
|
function at(a, indexes) {
|
||||||
let out = [];
|
const out = [];
|
||||||
for (let i = 0; i < indexes.length; i++) {
|
for (let i = 0; i < indexes.length; i++) {
|
||||||
out.push(a[indexes[i]]);
|
out.push(a[indexes[i]]);
|
||||||
}
|
}
|
||||||
@ -435,19 +435,19 @@ function at(a, indexes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createNTestFolders(n) {
|
async function createNTestFolders(n) {
|
||||||
let folders = [];
|
const folders = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let folder = await Folder.save({ title: 'folder' });
|
const folder = await Folder.save({ title: 'folder' });
|
||||||
folders.push(folder);
|
folders.push(folder);
|
||||||
}
|
}
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
|
async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
|
||||||
let notes = [];
|
const notes = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let title_ = n > 1 ? `${title}${i}` : title;
|
const title_ = n > 1 ? `${title}${i}` : title;
|
||||||
let note = await Note.save({ title: title_, parent_id: folder.id, is_conflict: 0 });
|
const note = await Note.save({ title: title_, parent_id: folder.id, is_conflict: 0 });
|
||||||
notes.push(note);
|
notes.push(note);
|
||||||
}
|
}
|
||||||
if (tagIds) {
|
if (tagIds) {
|
||||||
@ -459,9 +459,9 @@ async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createNTestTags(n) {
|
async function createNTestTags(n) {
|
||||||
let tags = [];
|
const tags = [];
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
let tag = await Tag.save({ title: 'tag' });
|
const tag = await Tag.save({ title: 'tag' });
|
||||||
tags.push(tag);
|
tags.push(tag);
|
||||||
}
|
}
|
||||||
return tags;
|
return tags;
|
||||||
|
@ -290,8 +290,8 @@
|
|||||||
// option to clip pages as HTML.
|
// option to clip pages as HTML.
|
||||||
function getStyleSheets(doc) {
|
function getStyleSheets(doc) {
|
||||||
const output = [];
|
const output = [];
|
||||||
for (var i=0; i<doc.styleSheets.length; i++) {
|
for (let i = 0; i < doc.styleSheets.length; i++) {
|
||||||
var sheet = doc.styleSheets[i];
|
const sheet = doc.styleSheets[i];
|
||||||
try {
|
try {
|
||||||
for (const cssRule of sheet.cssRules) {
|
for (const cssRule of sheet.cssRules) {
|
||||||
output.push({ type: 'text', value: cssRule.cssText });
|
output.push({ type: 'text', value: cssRule.cssText });
|
||||||
@ -530,7 +530,7 @@
|
|||||||
|
|
||||||
} else if (command.name === 'pageUrl') {
|
} else if (command.name === 'pageUrl') {
|
||||||
|
|
||||||
let url = pageLocationOrigin() + location.pathname + location.search;
|
const url = pageLocationOrigin() + location.pathname + location.search;
|
||||||
return clippedContentResponse(pageTitle(), url, getImageSizes(document), getAnchorNames(document));
|
return clippedContentResponse(pageTitle(), url, getImageSizes(document), getAnchorNames(document));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -18,7 +18,7 @@ require('../config/env');
|
|||||||
|
|
||||||
const jest = require('jest');
|
const jest = require('jest');
|
||||||
const execSync = require('child_process').execSync;
|
const execSync = require('child_process').execSync;
|
||||||
let argv = process.argv.slice(2);
|
const argv = process.argv.slice(2);
|
||||||
|
|
||||||
function isInGitRepository() {
|
function isInGitRepository() {
|
||||||
try {
|
try {
|
||||||
|
@ -85,7 +85,7 @@ class Application extends BaseApplication {
|
|||||||
const currentRoute = state.route;
|
const currentRoute = state.route;
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
newState = Object.assign({}, state);
|
||||||
let newNavHistory = state.navHistory.slice();
|
const newNavHistory = state.navHistory.slice();
|
||||||
|
|
||||||
if (goingBack) {
|
if (goingBack) {
|
||||||
let newAction = null;
|
let newAction = null;
|
||||||
@ -115,7 +115,7 @@ class Application extends BaseApplication {
|
|||||||
|
|
||||||
{
|
{
|
||||||
newState = Object.assign({}, state);
|
newState = Object.assign({}, state);
|
||||||
let command = Object.assign({}, action);
|
const command = Object.assign({}, action);
|
||||||
delete command.type;
|
delete command.type;
|
||||||
newState.windowCommand = command.name ? command : null;
|
newState.windowCommand = command.name ? command : null;
|
||||||
}
|
}
|
||||||
@ -143,13 +143,13 @@ class Application extends BaseApplication {
|
|||||||
const currentLayoutIndex = paneOptions.indexOf(currentLayout);
|
const currentLayoutIndex = paneOptions.indexOf(currentLayout);
|
||||||
const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1;
|
const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1;
|
||||||
|
|
||||||
let nextLayout = paneOptions[nextLayoutIndex];
|
const nextLayout = paneOptions[nextLayoutIndex];
|
||||||
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
|
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
|
||||||
};
|
};
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
newState = Object.assign({}, state);
|
||||||
|
|
||||||
let panes = state.noteVisiblePanes.slice();
|
const panes = state.noteVisiblePanes.slice();
|
||||||
newState.noteVisiblePanes = getNextLayout(panes);
|
newState.noteVisiblePanes = getNextLayout(panes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -328,7 +328,7 @@ class Application extends BaseApplication {
|
|||||||
const sortNoteFolderItems = (type) => {
|
const sortNoteFolderItems = (type) => {
|
||||||
const sortItems = [];
|
const sortItems = [];
|
||||||
const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`);
|
const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`);
|
||||||
for (let field in sortOptions) {
|
for (const field in sortOptions) {
|
||||||
if (!sortOptions.hasOwnProperty(field)) continue;
|
if (!sortOptions.hasOwnProperty(field)) continue;
|
||||||
sortItems.push({
|
sortItems.push({
|
||||||
label: sortOptions[field],
|
label: sortOptions[field],
|
||||||
@ -650,7 +650,7 @@ class Application extends BaseApplication {
|
|||||||
gitInfo = _('Revision: %s (%s)', p.git.hash, p.git.branch);
|
gitInfo = _('Revision: %s (%s)', p.git.hash, p.git.branch);
|
||||||
}
|
}
|
||||||
const copyrightText = 'Copyright © 2016-YYYY Laurent Cozic';
|
const copyrightText = 'Copyright © 2016-YYYY Laurent Cozic';
|
||||||
let message = [
|
const message = [
|
||||||
p.description,
|
p.description,
|
||||||
'',
|
'',
|
||||||
copyrightText.replace('YYYY', new Date().getFullYear()),
|
copyrightText.replace('YYYY', new Date().getFullYear()),
|
||||||
@ -1119,7 +1119,7 @@ class Application extends BaseApplication {
|
|||||||
|
|
||||||
const pluginMenuItems = PluginManager.instance().menuItems();
|
const pluginMenuItems = PluginManager.instance().menuItems();
|
||||||
for (const item of pluginMenuItems) {
|
for (const item of pluginMenuItems) {
|
||||||
let itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
|
const itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
|
||||||
itemParent.submenu.push(item);
|
itemParent.submenu.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1155,7 +1155,7 @@ class Application extends BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove empty separator for now empty sections
|
// Remove empty separator for now empty sections
|
||||||
let temp = [];
|
const temp = [];
|
||||||
let previous = null;
|
let previous = null;
|
||||||
for (let i = 0; i < output.length; i++) {
|
for (let i = 0; i < output.length; i++) {
|
||||||
const t = Object.assign({}, output[i]);
|
const t = Object.assign({}, output[i]);
|
||||||
@ -1171,7 +1171,7 @@ class Application extends BaseApplication {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
let screenTemplate = removeUnwantedItems(template, screen);
|
const screenTemplate = removeUnwantedItems(template, screen);
|
||||||
|
|
||||||
const menu = Menu.buildFromTemplate(screenTemplate);
|
const menu = Menu.buildFromTemplate(screenTemplate);
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
|
@ -57,7 +57,7 @@ class ClipperConfigScreenComponent extends React.Component {
|
|||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
let webClipperStatusComps = [];
|
const webClipperStatusComps = [];
|
||||||
|
|
||||||
if (this.props.clipperServerAutoStart) {
|
if (this.props.clipperServerAutoStart) {
|
||||||
webClipperStatusComps.push(
|
webClipperStatusComps.push(
|
||||||
|
@ -92,8 +92,8 @@ class ConfigScreenComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keyValueToArray(kv) {
|
keyValueToArray(kv) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let k in kv) {
|
for (const k in kv) {
|
||||||
if (!kv.hasOwnProperty(k)) continue;
|
if (!kv.hasOwnProperty(k)) continue;
|
||||||
output.push({
|
output.push({
|
||||||
key: k,
|
key: k,
|
||||||
@ -205,7 +205,7 @@ class ConfigScreenComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let advancedSettingsButton = null;
|
let advancedSettingsButton = null;
|
||||||
let advancedSettingsSectionStyle = { display: 'none' };
|
const advancedSettingsSectionStyle = { display: 'none' };
|
||||||
|
|
||||||
if (advancedSettingComps.length) {
|
if (advancedSettingComps.length) {
|
||||||
const iconName = this.state.showAdvancedSettings ? 'fa fa-toggle-up' : 'fa fa-toggle-down';
|
const iconName = this.state.showAdvancedSettings ? 'fa fa-toggle-up' : 'fa fa-toggle-down';
|
||||||
@ -227,7 +227,7 @@ class ConfigScreenComponent extends React.Component {
|
|||||||
settingToComponent(key, value) {
|
settingToComponent(key, value) {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
|
|
||||||
let output = null;
|
const output = null;
|
||||||
|
|
||||||
const rowStyle = this.rowStyle_;
|
const rowStyle = this.rowStyle_;
|
||||||
|
|
||||||
@ -283,9 +283,9 @@ class ConfigScreenComponent extends React.Component {
|
|||||||
const descriptionComp = descriptionText ? <div style={descriptionStyle}>{descriptionText}</div> : null;
|
const descriptionComp = descriptionText ? <div style={descriptionStyle}>{descriptionText}</div> : null;
|
||||||
|
|
||||||
if (md.isEnum) {
|
if (md.isEnum) {
|
||||||
let items = [];
|
const items = [];
|
||||||
const settingOptions = md.options();
|
const settingOptions = md.options();
|
||||||
let array = this.keyValueToArray(settingOptions);
|
const array = this.keyValueToArray(settingOptions);
|
||||||
for (let i = 0; i < array.length; i++) {
|
for (let i = 0; i < array.length; i++) {
|
||||||
const e = array[i];
|
const e = array[i];
|
||||||
items.push(
|
items.push(
|
||||||
@ -547,7 +547,7 @@ class ConfigScreenComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let settings = this.state.settings;
|
const settings = this.state.settings;
|
||||||
|
|
||||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0, display: 'flex', flex: 1 });
|
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0, display: 'flex', flex: 1 });
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ class EncryptionConfigScreenComponent extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mkComps = [];
|
const mkComps = [];
|
||||||
let nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice();
|
const nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice();
|
||||||
|
|
||||||
for (let i = 0; i < masterKeys.length; i++) {
|
for (let i = 0; i < masterKeys.length; i++) {
|
||||||
const mk = masterKeys[i];
|
const mk = masterKeys[i];
|
||||||
|
@ -149,7 +149,7 @@ class HeaderComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isEnabled = !('enabled' in options) || options.enabled;
|
const isEnabled = !('enabled' in options) || options.enabled;
|
||||||
let classes = ['button'];
|
const classes = ['button'];
|
||||||
if (!isEnabled) classes.push('disabled');
|
if (!isEnabled) classes.push('disabled');
|
||||||
|
|
||||||
const finalStyle = Object.assign({}, style, {
|
const finalStyle = Object.assign({}, style, {
|
||||||
|
@ -15,7 +15,7 @@ class HelpButtonComponent extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
let style = Object.assign({}, this.props.style, { color: theme.color, textDecoration: 'none' });
|
const style = Object.assign({}, this.props.style, { color: theme.color, textDecoration: 'none' });
|
||||||
const helpIconStyle = { flex: 0, width: 16, height: 16, marginLeft: 10 };
|
const helpIconStyle = { flex: 0, width: 16, height: 16, marginLeft: 10 };
|
||||||
const extraProps = {};
|
const extraProps = {};
|
||||||
if (this.props.tip) extraProps['data-tip'] = this.props.tip;
|
if (this.props.tip) extraProps['data-tip'] = this.props.tip;
|
||||||
|
@ -46,9 +46,9 @@ class ImportScreenComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uniqueMessages() {
|
uniqueMessages() {
|
||||||
let output = [];
|
const output = [];
|
||||||
const messages = this.state.messages.slice();
|
const messages = this.state.messages.slice();
|
||||||
let foundKeys = [];
|
const foundKeys = [];
|
||||||
for (let i = messages.length - 1; i >= 0; i--) {
|
for (let i = messages.length - 1; i >= 0; i--) {
|
||||||
const msg = messages[i];
|
const msg = messages[i];
|
||||||
if (foundKeys.indexOf(msg.key) >= 0) continue;
|
if (foundKeys.indexOf(msg.key) >= 0) continue;
|
||||||
@ -68,7 +68,7 @@ class ImportScreenComponent extends React.Component {
|
|||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
onProgress: progressState => {
|
onProgress: progressState => {
|
||||||
let line = [];
|
const line = [];
|
||||||
line.push(_('Found: %d.', progressState.loaded));
|
line.push(_('Found: %d.', progressState.loaded));
|
||||||
line.push(_('Created: %d.', progressState.created));
|
line.push(_('Created: %d.', progressState.created));
|
||||||
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
||||||
|
@ -83,7 +83,7 @@ class ItemList extends React.Component {
|
|||||||
return <div key={key} style={{ height: height }}></div>;
|
return <div key={key} style={{ height: height }}></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
let itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)];
|
const itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)];
|
||||||
|
|
||||||
for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) {
|
for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) {
|
||||||
const itemComp = this.props.itemRenderer(items[i]);
|
const itemComp = this.props.itemRenderer(items[i]);
|
||||||
@ -92,7 +92,7 @@ class ItemList extends React.Component {
|
|||||||
|
|
||||||
itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight));
|
itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight));
|
||||||
|
|
||||||
let classes = ['item-list'];
|
const classes = ['item-list'];
|
||||||
if (this.props.className) classes.push(this.props.className);
|
if (this.props.className) classes.push(this.props.className);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -324,7 +324,7 @@ class MainScreenComponent extends React.Component {
|
|||||||
} else if (command.name === 'editAlarm') {
|
} else if (command.name === 'editAlarm') {
|
||||||
const note = await Note.load(command.noteId);
|
const note = await Note.load(command.noteId);
|
||||||
|
|
||||||
let defaultDate = new Date(Date.now() + 2 * 3600 * 1000);
|
const defaultDate = new Date(Date.now() + 2 * 3600 * 1000);
|
||||||
defaultDate.setMinutes(0);
|
defaultDate.setMinutes(0);
|
||||||
defaultDate.setSeconds(0);
|
defaultDate.setSeconds(0);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ class NavigatorComponent extends Component {
|
|||||||
UNSAFE_componentWillReceiveProps(newProps) {
|
UNSAFE_componentWillReceiveProps(newProps) {
|
||||||
if (newProps.route) {
|
if (newProps.route) {
|
||||||
const screenInfo = this.props.screens[newProps.route.routeName];
|
const screenInfo = this.props.screens[newProps.route.routeName];
|
||||||
let windowTitle = ['Joplin'];
|
const windowTitle = ['Joplin'];
|
||||||
if (screenInfo.title) {
|
if (screenInfo.title) {
|
||||||
windowTitle.push(screenInfo.title());
|
windowTitle.push(screenInfo.title());
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ export default function NoteContentPropertiesDialog(props:NoteContentPropertiesD
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (textProperties) {
|
if (textProperties) {
|
||||||
for (let key in textProperties) {
|
for (const key in textProperties) {
|
||||||
if (!textProperties.hasOwnProperty(key)) continue;
|
if (!textProperties.hasOwnProperty(key)) continue;
|
||||||
const comp = createItemField(key, textProperties[key]);
|
const comp = createItemField(key, textProperties[key]);
|
||||||
textComps.push(comp);
|
textComps.push(comp);
|
||||||
|
@ -34,7 +34,7 @@ class NoteListComponent extends React.Component {
|
|||||||
// Pull request: https://github.com/laurent22/joplin/pull/2062
|
// Pull request: https://github.com/laurent22/joplin/pull/2062
|
||||||
const itemWidth = '100%';
|
const itemWidth = '100%';
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
},
|
},
|
||||||
@ -184,7 +184,7 @@ class NoteListComponent extends React.Component {
|
|||||||
listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4;
|
listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4;
|
||||||
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted);
|
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted);
|
||||||
|
|
||||||
let displayTitle = Note.displayTitle(item);
|
const displayTitle = Note.displayTitle(item);
|
||||||
let titleComp = null;
|
let titleComp = null;
|
||||||
|
|
||||||
if (highlightedWords.length) {
|
if (highlightedWords.length) {
|
||||||
@ -435,7 +435,7 @@ class NoteListComponent extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
const style = this.props.style;
|
const style = this.props.style;
|
||||||
let notes = this.props.notes.slice();
|
const notes = this.props.notes.slice();
|
||||||
|
|
||||||
if (!notes.length) {
|
if (!notes.length) {
|
||||||
const padding = 10;
|
const padding = 10;
|
||||||
|
@ -361,7 +361,7 @@ class NotePropertiesDialog extends React.Component {
|
|||||||
const noteComps = [];
|
const noteComps = [];
|
||||||
|
|
||||||
if (formNote) {
|
if (formNote) {
|
||||||
for (let key in formNote) {
|
for (const key in formNote) {
|
||||||
if (!formNote.hasOwnProperty(key)) continue;
|
if (!formNote.hasOwnProperty(key)) continue;
|
||||||
const comp = this.createNoteField(key, formNote[key]);
|
const comp = this.createNoteField(key, formNote[key]);
|
||||||
noteComps.push(comp);
|
noteComps.push(comp);
|
||||||
|
@ -40,7 +40,7 @@ class NoteRevisionViewerComponent extends React.PureComponent {
|
|||||||
style() {
|
style() {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -19,7 +19,7 @@ class NoteSearchBarComponent extends React.Component {
|
|||||||
style() {
|
style() {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
root: Object.assign({}, theme.textStyle, {
|
root: Object.assign({}, theme.textStyle, {
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
color: theme.colorFaded,
|
color: theme.colorFaded,
|
||||||
@ -130,7 +130,7 @@ class NoteSearchBarComponent extends React.Component {
|
|||||||
if (this.backgroundColor === undefined) {
|
if (this.backgroundColor === undefined) {
|
||||||
this.backgroundColor = theme.backgroundColor;
|
this.backgroundColor = theme.backgroundColor;
|
||||||
}
|
}
|
||||||
let buttonEnabled = (this.backgroundColor === theme.backgroundColor);
|
const buttonEnabled = (this.backgroundColor === theme.backgroundColor);
|
||||||
|
|
||||||
const closeButton = this.buttonIconComponent('fa-times', this.closeButton_click, true);
|
const closeButton = this.buttonIconComponent('fa-times', this.closeButton_click, true);
|
||||||
const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled);
|
const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled);
|
||||||
|
@ -7,7 +7,7 @@ class NoteStatusBarComponent extends React.Component {
|
|||||||
style() {
|
style() {
|
||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
root: Object.assign({}, theme.textStyle, {
|
root: Object.assign({}, theme.textStyle, {
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
color: theme.colorFaded,
|
color: theme.colorFaded,
|
||||||
|
@ -543,22 +543,22 @@ class NoteTextComponent extends React.Component {
|
|||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
const stateNoteId = this.state.note ? this.state.note.id : null;
|
const stateNoteId = this.state.note ? this.state.note.id : null;
|
||||||
let noteId = props.noteId;
|
const noteId = props.noteId;
|
||||||
let parentFolder = null;
|
let parentFolder = null;
|
||||||
const isProvisionalNote = this.props.provisionalNoteIds.includes(noteId);
|
const isProvisionalNote = this.props.provisionalNoteIds.includes(noteId);
|
||||||
|
|
||||||
let scrollPercent = this.props.lastEditorScrollPercents[noteId];
|
let scrollPercent = this.props.lastEditorScrollPercents[noteId];
|
||||||
if (!scrollPercent) scrollPercent = 0;
|
if (!scrollPercent) scrollPercent = 0;
|
||||||
|
|
||||||
let loadingNewNote = stateNoteId !== noteId;
|
const loadingNewNote = stateNoteId !== noteId;
|
||||||
this.lastLoadedNoteId_ = noteId;
|
this.lastLoadedNoteId_ = noteId;
|
||||||
let note = noteId ? await Note.load(noteId) : null;
|
const note = noteId ? await Note.load(noteId) : null;
|
||||||
if (noteId !== this.lastLoadedNoteId_) return defer(); // Race condition - current note was changed while this one was loading
|
if (noteId !== this.lastLoadedNoteId_) return defer(); // Race condition - current note was changed while this one was loading
|
||||||
if (options.noReloadIfLocalChanges && this.isModified()) return defer();
|
if (options.noReloadIfLocalChanges && this.isModified()) return defer();
|
||||||
|
|
||||||
// If the note hasn't been changed, exit now
|
// If the note hasn't been changed, exit now
|
||||||
if (this.state.note && note) {
|
if (this.state.note && note) {
|
||||||
let diff = Note.diffObjects(this.state.note, note);
|
const diff = Note.diffObjects(this.state.note, note);
|
||||||
delete diff.type_;
|
delete diff.type_;
|
||||||
if (!Object.getOwnPropertyNames(diff).length) return defer();
|
if (!Object.getOwnPropertyNames(diff).length) return defer();
|
||||||
}
|
}
|
||||||
@ -622,7 +622,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
parentFolder = Folder.byId(props.folders, note.parent_id);
|
parentFolder = Folder.byId(props.folders, note.parent_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let newState = {
|
const newState = {
|
||||||
note: note,
|
note: note,
|
||||||
lastSavedNote: Object.assign({}, note),
|
lastSavedNote: Object.assign({}, note),
|
||||||
webviewReady: webviewReady,
|
webviewReady: webviewReady,
|
||||||
@ -686,9 +686,9 @@ class NoteTextComponent extends React.Component {
|
|||||||
|
|
||||||
for (let i = 0; i < newTags.length; ++i) {
|
for (let i = 0; i < newTags.length; ++i) {
|
||||||
let found = false;
|
let found = false;
|
||||||
let currNewTag = newTags[i];
|
const currNewTag = newTags[i];
|
||||||
for (let j = 0; j < oldTags.length; ++j) {
|
for (let j = 0; j < oldTags.length; ++j) {
|
||||||
let currOldTag = oldTags[j];
|
const currOldTag = oldTags[j];
|
||||||
if (currOldTag.id === currNewTag.id) {
|
if (currOldTag.id === currNewTag.id) {
|
||||||
found = true;
|
found = true;
|
||||||
if (currOldTag.updated_time !== currNewTag.updated_time) {
|
if (currOldTag.updated_time !== currNewTag.updated_time) {
|
||||||
@ -1299,7 +1299,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
try {
|
try {
|
||||||
if (!this.state.note && !args.noteIds) throw new Error('No notes selected for pdf export');
|
if (!this.state.note && !args.noteIds) throw new Error('No notes selected for pdf export');
|
||||||
|
|
||||||
let noteIds = args.noteIds ? args.noteIds : [this.state.note.id];
|
const noteIds = args.noteIds ? args.noteIds : [this.state.note.id];
|
||||||
|
|
||||||
let path = null;
|
let path = null;
|
||||||
if (noteIds.length === 1) {
|
if (noteIds.length === 1) {
|
||||||
@ -1452,14 +1452,14 @@ class NoteTextComponent extends React.Component {
|
|||||||
|
|
||||||
if (selection && selection.start !== selection.end) {
|
if (selection && selection.start !== selection.end) {
|
||||||
const selectedLines = replacementText !== null ? replacementText : this.state.note.body.substr(selection.start, selection.end - selection.start);
|
const selectedLines = replacementText !== null ? replacementText : this.state.note.body.substr(selection.start, selection.end - selection.start);
|
||||||
let selectedStrings = byLine ? selectedLines.split(/\r?\n/) : [selectedLines];
|
const selectedStrings = byLine ? selectedLines.split(/\r?\n/) : [selectedLines];
|
||||||
|
|
||||||
newBody = this.state.note.body.substr(0, selection.start);
|
newBody = this.state.note.body.substr(0, selection.start);
|
||||||
|
|
||||||
for (let i = 0; i < selectedStrings.length; i++) {
|
for (let i = 0; i < selectedStrings.length; i++) {
|
||||||
if (byLine == false) {
|
if (byLine == false) {
|
||||||
let start = selectedStrings[i].search(/[^\s]/);
|
const start = selectedStrings[i].search(/[^\s]/);
|
||||||
let end = selectedStrings[i].search(/[^\s](?=[\s]*$)/);
|
const end = selectedStrings[i].search(/[^\s](?=[\s]*$)/);
|
||||||
newBody += selectedStrings[i].substr(0, start) + string1 + selectedStrings[i].substr(start, end - start + 1) + string2 + selectedStrings[i].substr(end + 1);
|
newBody += selectedStrings[i].substr(0, start) + string1 + selectedStrings[i].substr(start, end - start + 1) + string2 + selectedStrings[i].substr(end + 1);
|
||||||
if (this.state.note.body.substr(selection.end) === '') newBody = newBody.trim();
|
if (this.state.note.body.substr(selection.end) === '') newBody = newBody.trim();
|
||||||
} else { newBody += string1 + selectedStrings[i] + string2; }
|
} else { newBody += string1 + selectedStrings[i] + string2; }
|
||||||
@ -1498,7 +1498,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
editor.focus();
|
editor.focus();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let middleText = replacementText !== null ? replacementText : defaultText;
|
const middleText = replacementText !== null ? replacementText : defaultText;
|
||||||
const textOffset = this.currentTextOffset();
|
const textOffset = this.currentTextOffset();
|
||||||
const s1 = this.state.note.body.substr(0, textOffset);
|
const s1 = this.state.note.body.substr(0, textOffset);
|
||||||
const s2 = this.state.note.body.substr(textOffset);
|
const s2 = this.state.note.body.substr(textOffset);
|
||||||
@ -1541,9 +1541,9 @@ class NoteTextComponent extends React.Component {
|
|||||||
|
|
||||||
toggleWrapSelection(strings1, strings2, defaultText) {
|
toggleWrapSelection(strings1, strings2, defaultText) {
|
||||||
const selection = this.textOffsetSelection();
|
const selection = this.textOffsetSelection();
|
||||||
let string = this.state.note.body.substr(selection.start, selection.end - selection.start);
|
const string = this.state.note.body.substr(selection.start, selection.end - selection.start);
|
||||||
let replaced = false;
|
let replaced = false;
|
||||||
for (var i = 0; i < strings1.length; i++) {
|
for (let i = 0; i < strings1.length; i++) {
|
||||||
if (string.startsWith(strings1[i]) && string.endsWith(strings1[i])) {
|
if (string.startsWith(strings1[i]) && string.endsWith(strings1[i])) {
|
||||||
this.wrapSelectionWithStrings('', '', '', string.substr(strings1[i].length, selection.end - selection.start - (2 * strings1[i].length)));
|
this.wrapSelectionWithStrings('', '', '', string.substr(strings1[i].length, selection.end - selection.start - (2 * strings1[i].length)));
|
||||||
replaced = true;
|
replaced = true;
|
||||||
@ -1570,10 +1570,10 @@ class NoteTextComponent extends React.Component {
|
|||||||
|
|
||||||
commandTextCode() {
|
commandTextCode() {
|
||||||
const selection = this.textOffsetSelection();
|
const selection = this.textOffsetSelection();
|
||||||
let string = this.state.note.body.substr(selection.start, selection.end - selection.start);
|
const string = this.state.note.body.substr(selection.start, selection.end - selection.start);
|
||||||
|
|
||||||
// Look for newlines
|
// Look for newlines
|
||||||
let match = string.match(/\r?\n/);
|
const match = string.match(/\r?\n/);
|
||||||
|
|
||||||
if (match && match.length > 0) {
|
if (match && match.length > 0) {
|
||||||
// Follow the same newline style
|
// Follow the same newline style
|
||||||
@ -1591,7 +1591,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
this.wrapSelectionWithStrings(TemplateUtils.render(value));
|
this.wrapSelectionWithStrings(TemplateUtils.render(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
addListItem(string1, string2 = '', defaultText = '', byLine=false) {
|
addListItem(string1, string2 = '', defaultText = '', byLine = false) {
|
||||||
let newLine = '\n';
|
let newLine = '\n';
|
||||||
const range = this.selectionRange_;
|
const range = this.selectionRange_;
|
||||||
if (!range || (range.start.row === range.end.row && !this.selectionRangeCurrentLine())) {
|
if (!range || (range.start.row === range.end.row && !this.selectionRangeCurrentLine())) {
|
||||||
@ -1949,7 +1949,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
|
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
|
||||||
const isTodo = note && !!note.is_todo;
|
const isTodo = note && !!note.is_todo;
|
||||||
var keyboardMode = this.props.keyboardMode;
|
let keyboardMode = this.props.keyboardMode;
|
||||||
if (keyboardMode === 'default' || !keyboardMode) {
|
if (keyboardMode === 'default' || !keyboardMode) {
|
||||||
keyboardMode = null;
|
keyboardMode = null;
|
||||||
}
|
}
|
||||||
@ -2006,7 +2006,7 @@ class NoteTextComponent extends React.Component {
|
|||||||
paddingRight: 8,
|
paddingRight: 8,
|
||||||
marginRight: rootStyle.paddingLeft,
|
marginRight: rootStyle.paddingLeft,
|
||||||
color: theme.textStyle.color,
|
color: theme.textStyle.color,
|
||||||
fontSize: theme.textStyle.fontSize * 1.25 *1.5,
|
fontSize: theme.textStyle.fontSize * 1.25 * 1.5,
|
||||||
backgroundColor: theme.backgroundColor,
|
backgroundColor: theme.backgroundColor,
|
||||||
border: '1px solid',
|
border: '1px solid',
|
||||||
borderColor: theme.dividerColor,
|
borderColor: theme.dividerColor,
|
||||||
@ -2083,11 +2083,11 @@ class NoteTextComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.webviewReady && this.webviewRef_.current) {
|
if (this.state.webviewReady && this.webviewRef_.current) {
|
||||||
let html = this.state.bodyHtml;
|
const html = this.state.bodyHtml;
|
||||||
|
|
||||||
const htmlHasChanged = this.lastSetHtml_ !== html;
|
const htmlHasChanged = this.lastSetHtml_ !== html;
|
||||||
if (htmlHasChanged) {
|
if (htmlHasChanged) {
|
||||||
let options = {
|
const options = {
|
||||||
pluginAssets: this.state.lastRenderPluginAssets,
|
pluginAssets: this.state.lastRenderPluginAssets,
|
||||||
downloadResources: Setting.value('sync.resourceDownloadMode'),
|
downloadResources: Setting.value('sync.resourceDownloadMode'),
|
||||||
};
|
};
|
||||||
|
@ -57,7 +57,7 @@ class NoteTextViewerComponent extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let n in this.webviewListeners_) {
|
for (const n in this.webviewListeners_) {
|
||||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||||
const fn = this.webviewListeners_[n];
|
const fn = this.webviewListeners_[n];
|
||||||
wv.addEventListener(n, fn);
|
wv.addEventListener(n, fn);
|
||||||
@ -70,7 +70,7 @@ class NoteTextViewerComponent extends React.Component {
|
|||||||
const wv = this.webviewRef_.current;
|
const wv = this.webviewRef_.current;
|
||||||
if (!wv || !this.initialized_) return;
|
if (!wv || !this.initialized_) return;
|
||||||
|
|
||||||
for (let n in this.webviewListeners_) {
|
for (const n in this.webviewListeners_) {
|
||||||
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
if (!this.webviewListeners_.hasOwnProperty(n)) continue;
|
||||||
const fn = this.webviewListeners_[n];
|
const fn = this.webviewListeners_[n];
|
||||||
wv.removeEventListener(n, fn);
|
wv.removeEventListener(n, fn);
|
||||||
|
@ -73,7 +73,7 @@ export default function ShareNoteDialog(props:ShareNoteDialogProps) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchNotes() {
|
async function fetchNotes() {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (let noteId of props.noteIds) {
|
for (const noteId of props.noteIds) {
|
||||||
result.push(await Note.load(noteId));
|
result.push(await Note.load(noteId));
|
||||||
}
|
}
|
||||||
setNotes(result);
|
setNotes(result);
|
||||||
@ -180,7 +180,7 @@ export default function ShareNoteDialog(props:ShareNoteDialogProps) {
|
|||||||
|
|
||||||
const renderNoteList = (notes:any) => {
|
const renderNoteList = (notes:any) => {
|
||||||
const noteComps = [];
|
const noteComps = [];
|
||||||
for (let noteId of Object.keys(notes)) {
|
for (const noteId of Object.keys(notes)) {
|
||||||
noteComps.push(renderNote(notes[noteId]));
|
noteComps.push(renderNote(notes[noteId]));
|
||||||
}
|
}
|
||||||
return <div style={styles.noteList}>{noteComps}</div>;
|
return <div style={styles.noteList}>{noteComps}</div>;
|
||||||
|
@ -107,7 +107,7 @@ class SideBarComponent extends React.Component {
|
|||||||
|
|
||||||
const itemHeight = 25;
|
const itemHeight = 25;
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: theme.backgroundColor2,
|
backgroundColor: theme.backgroundColor2,
|
||||||
},
|
},
|
||||||
@ -459,8 +459,8 @@ class SideBarComponent extends React.Component {
|
|||||||
let containerStyle = Object.assign({}, this.style(depth).listItemContainer);
|
let containerStyle = Object.assign({}, this.style(depth).listItemContainer);
|
||||||
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
|
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
|
||||||
|
|
||||||
let expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
|
const expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
|
||||||
let expandIconStyle = {
|
const expandIconStyle = {
|
||||||
visibility: hasChildren ? 'visible' : 'hidden',
|
visibility: hasChildren ? 'visible' : 'hidden',
|
||||||
paddingLeft: 8 + depth * 10,
|
paddingLeft: 8 + depth * 10,
|
||||||
};
|
};
|
||||||
@ -562,18 +562,18 @@ class SideBarComponent extends React.Component {
|
|||||||
style.cursor = 'pointer';
|
style.cursor = 'pointer';
|
||||||
}
|
}
|
||||||
|
|
||||||
let headerClick = extraProps.onClick || null;
|
const headerClick = extraProps.onClick || null;
|
||||||
delete extraProps.onClick;
|
delete extraProps.onClick;
|
||||||
|
|
||||||
// check if toggling option is set.
|
// check if toggling option is set.
|
||||||
let toggleIcon = null;
|
let toggleIcon = null;
|
||||||
const toggleKey = `${key}IsExpanded`;
|
const toggleKey = `${key}IsExpanded`;
|
||||||
if (extraProps.toggleblock) {
|
if (extraProps.toggleblock) {
|
||||||
let isExpanded = this.state[toggleKey];
|
const isExpanded = this.state[toggleKey];
|
||||||
toggleIcon = <i className={`fa ${isExpanded ? 'fa-chevron-down' : 'fa-chevron-left'}`} style={{ fontSize: style.fontSize * 0.75, marginRight: 12, marginLeft: 5, marginTop: style.fontSize * 0.125 }}></i>;
|
toggleIcon = <i className={`fa ${isExpanded ? 'fa-chevron-down' : 'fa-chevron-left'}`} style={{ fontSize: style.fontSize * 0.75, marginRight: 12, marginLeft: 5, marginTop: style.fontSize * 0.125 }}></i>;
|
||||||
}
|
}
|
||||||
if (extraProps.selected) {
|
if (extraProps.selected) {
|
||||||
style.backgroundColor =this.style().listItemSelected.backgroundColor;
|
style.backgroundColor = this.style().listItemSelected.backgroundColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ref = this.anchorItemRef('headers', key);
|
const ref = this.anchorItemRef('headers', key);
|
||||||
@ -645,7 +645,7 @@ class SideBarComponent extends React.Component {
|
|||||||
|
|
||||||
const focusItem = focusItems[newIndex];
|
const focusItem = focusItems[newIndex];
|
||||||
|
|
||||||
let actionName = `${focusItem.type.toUpperCase()}_SELECT`;
|
const actionName = `${focusItem.type.toUpperCase()}_SELECT`;
|
||||||
|
|
||||||
this.props.dispatch({
|
this.props.dispatch({
|
||||||
type: actionName,
|
type: actionName,
|
||||||
@ -712,7 +712,7 @@ class SideBarComponent extends React.Component {
|
|||||||
const style = Object.assign({}, this.style().button, { marginBottom: 5 });
|
const style = Object.assign({}, this.style().button, { marginBottom: 5 });
|
||||||
const iconName = 'fa-refresh';
|
const iconName = 'fa-refresh';
|
||||||
const label = type === 'sync' ? _('Synchronise') : _('Cancel');
|
const label = type === 'sync' ? _('Synchronise') : _('Cancel');
|
||||||
let iconStyle = { fontSize: style.fontSize, marginRight: 5 };
|
const iconStyle = { fontSize: style.fontSize, marginRight: 5 };
|
||||||
|
|
||||||
if (type !== 'sync') {
|
if (type !== 'sync') {
|
||||||
iconStyle.animation = 'icon-infinite-rotation 1s linear infinite';
|
iconStyle.animation = 'icon-infinite-rotation 1s linear infinite';
|
||||||
@ -743,7 +743,7 @@ class SideBarComponent extends React.Component {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
});
|
});
|
||||||
|
|
||||||
let items = [];
|
const items = [];
|
||||||
items.push(
|
items.push(
|
||||||
this.makeHeader('allNotesHeader', _('All notes'), 'fa-clone', {
|
this.makeHeader('allNotesHeader', _('All notes'), 'fa-clone', {
|
||||||
onClick: this.onAllNotesClick_,
|
onClick: this.onAllNotesClick_,
|
||||||
@ -798,7 +798,7 @@ class SideBarComponent extends React.Component {
|
|||||||
resourceFetcherText = _('Fetching resources: %d/%d', this.props.resourceFetcher.fetchingCount, this.props.resourceFetcher.toFetchCount);
|
resourceFetcherText = _('Fetching resources: %d/%d', this.props.resourceFetcher.fetchingCount, this.props.resourceFetcher.toFetchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lines = Synchronizer.reportToLines(this.props.syncReport);
|
const lines = Synchronizer.reportToLines(this.props.syncReport);
|
||||||
if (resourceFetcherText) lines.push(resourceFetcherText);
|
if (resourceFetcherText) lines.push(resourceFetcherText);
|
||||||
if (decryptionReportText) lines.push(decryptionReportText);
|
if (decryptionReportText) lines.push(decryptionReportText);
|
||||||
const syncReportText = [];
|
const syncReportText = [];
|
||||||
|
@ -64,13 +64,13 @@ class StatusScreenComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderSectionHtml = (key, section) => {
|
const renderSectionHtml = (key, section) => {
|
||||||
let itemsHtml = [];
|
const itemsHtml = [];
|
||||||
|
|
||||||
itemsHtml.push(renderSectionTitleHtml(section.title, section.title));
|
itemsHtml.push(renderSectionTitleHtml(section.title, section.title));
|
||||||
|
|
||||||
for (let n in section.body) {
|
for (const n in section.body) {
|
||||||
if (!section.body.hasOwnProperty(n)) continue;
|
if (!section.body.hasOwnProperty(n)) continue;
|
||||||
let item = section.body[n];
|
const item = section.body[n];
|
||||||
let text = '';
|
let text = '';
|
||||||
|
|
||||||
let retryLink = null;
|
let retryLink = null;
|
||||||
@ -106,10 +106,10 @@ class StatusScreenComponent extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function renderBodyHtml(report) {
|
function renderBodyHtml(report) {
|
||||||
let sectionsHtml = [];
|
const sectionsHtml = [];
|
||||||
|
|
||||||
for (let i = 0; i < report.length; i++) {
|
for (let i = 0; i < report.length; i++) {
|
||||||
let section = report[i];
|
const section = report[i];
|
||||||
if (!section.body.length) continue;
|
if (!section.body.length) continue;
|
||||||
sectionsHtml.push(renderSectionHtml(i, section));
|
sectionsHtml.push(renderSectionHtml(i, section));
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ class StatusScreenComponent extends React.Component {
|
|||||||
return <div>{sectionsHtml}</div>;
|
return <div>{sectionsHtml}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = renderBodyHtml(this.state.report);
|
const body = renderBodyHtml(this.state.report);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={style}>
|
<div style={style}>
|
||||||
|
@ -21,7 +21,7 @@ class ToolbarButton extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isEnabled = !('enabled' in this.props) || this.props.enabled === true;
|
const isEnabled = !('enabled' in this.props) || this.props.enabled === true;
|
||||||
let classes = ['button'];
|
const classes = ['button'];
|
||||||
if (!isEnabled) classes.push('disabled');
|
if (!isEnabled) classes.push('disabled');
|
||||||
|
|
||||||
const finalStyle = Object.assign({}, style, {
|
const finalStyle = Object.assign({}, style, {
|
||||||
|
@ -100,7 +100,7 @@ app().start(bridge().processArgv()).then(() => {
|
|||||||
} else {
|
} else {
|
||||||
// If something goes wrong at this stage we don't have a console or a log file
|
// If something goes wrong at this stage we don't have a console or a log file
|
||||||
// so display the error in a message box.
|
// so display the error in a message box.
|
||||||
let msg = ['Fatal error:', error.message];
|
const msg = ['Fatal error:', error.message];
|
||||||
if (error.fileName) msg.push(error.fileName);
|
if (error.fileName) msg.push(error.fileName);
|
||||||
if (error.lineNumber) msg.push(error.lineNumber);
|
if (error.lineNumber) msg.push(error.lineNumber);
|
||||||
if (error.stack) msg.push(error.stack);
|
if (error.stack) msg.push(error.stack);
|
||||||
|
@ -385,13 +385,13 @@ function addExtraStyles(style) {
|
|||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
let themeCache_ = {};
|
const themeCache_ = {};
|
||||||
|
|
||||||
function themeStyle(theme) {
|
function themeStyle(theme) {
|
||||||
if (!theme) throw new Error('Theme must be specified');
|
if (!theme) throw new Error('Theme must be specified');
|
||||||
|
|
||||||
var zoomRatio = 1; // Setting.value('style.zoom') / 100;
|
const zoomRatio = 1; // Setting.value('style.zoom') / 100;
|
||||||
var editorFontSize = Setting.value('style.editor.fontSize');
|
const editorFontSize = Setting.value('style.editor.fontSize');
|
||||||
|
|
||||||
const cacheKey = [theme, zoomRatio, editorFontSize].join('-');
|
const cacheKey = [theme, zoomRatio, editorFontSize].join('-');
|
||||||
if (themeCache_[cacheKey]) return themeCache_[cacheKey];
|
if (themeCache_[cacheKey]) return themeCache_[cacheKey];
|
||||||
@ -399,7 +399,7 @@ function themeStyle(theme) {
|
|||||||
// Font size are not theme specific, but they must be referenced
|
// Font size are not theme specific, but they must be referenced
|
||||||
// and computed here to allow them to respond to settings changes
|
// and computed here to allow them to respond to settings changes
|
||||||
// without the need to restart
|
// without the need to restart
|
||||||
let fontSizes = {
|
const fontSizes = {
|
||||||
fontSize: Math.round(globalStyle.fontSize * zoomRatio),
|
fontSize: Math.round(globalStyle.fontSize * zoomRatio),
|
||||||
editorFontSize: editorFontSize,
|
editorFontSize: editorFontSize,
|
||||||
textAreaLineHeight: Math.round(globalStyle.textAreaLineHeight * editorFontSize / 12),
|
textAreaLineHeight: Math.round(globalStyle.textAreaLineHeight * editorFontSize / 12),
|
||||||
|
@ -7,7 +7,7 @@ const execSync = require('child_process').execSync;
|
|||||||
const packageInfo = require(`${__dirname}/../package.json`);
|
const packageInfo = require(`${__dirname}/../package.json`);
|
||||||
|
|
||||||
module.exports = async function() {
|
module.exports = async function() {
|
||||||
let removeKeys = ['scripts', 'devDependencies', 'optionalDependencies', 'dependencies'];
|
const removeKeys = ['scripts', 'devDependencies', 'optionalDependencies', 'dependencies'];
|
||||||
|
|
||||||
for (let i = 0; i < removeKeys.length; i++) {
|
for (let i = 0; i < removeKeys.length; i++) {
|
||||||
delete packageInfo[removeKeys[i]];
|
delete packageInfo[removeKeys[i]];
|
||||||
|
@ -36,7 +36,7 @@ export default class PluginAssetsLoader {
|
|||||||
this.logger().info(`PluginAssetsLoader: Importing assets to ${destDir}`);
|
this.logger().info(`PluginAssetsLoader: Importing assets to ${destDir}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (let name in pluginAssets.files) {
|
for (const name in pluginAssets.files) {
|
||||||
const dataBase64 = pluginAssets.files[name].data;
|
const dataBase64 = pluginAssets.files[name].data;
|
||||||
const destPath = `${destDir}/${name}`;
|
const destPath = `${destDir}/${name}`;
|
||||||
await shim.fsDriver().mkdir(dirname(destPath));
|
await shim.fsDriver().mkdir(dirname(destPath));
|
||||||
|
@ -16,7 +16,7 @@ ArrayUtils.removeElement = function(array, element) {
|
|||||||
|
|
||||||
// https://stackoverflow.com/a/10264318/561309
|
// https://stackoverflow.com/a/10264318/561309
|
||||||
ArrayUtils.binarySearch = function(items, value) {
|
ArrayUtils.binarySearch = function(items, value) {
|
||||||
var startIndex = 0,
|
let startIndex = 0,
|
||||||
stopIndex = items.length - 1,
|
stopIndex = items.length - 1,
|
||||||
middle = Math.floor((stopIndex + startIndex) / 2);
|
middle = Math.floor((stopIndex + startIndex) / 2);
|
||||||
|
|
||||||
|
@ -111,13 +111,13 @@ class BaseApplication {
|
|||||||
// Handles the initial flags passed to main script and
|
// Handles the initial flags passed to main script and
|
||||||
// returns the remaining args.
|
// returns the remaining args.
|
||||||
async handleStartFlags_(argv, setDefaults = true) {
|
async handleStartFlags_(argv, setDefaults = true) {
|
||||||
let matched = {};
|
const matched = {};
|
||||||
argv = argv.slice(0);
|
argv = argv.slice(0);
|
||||||
argv.splice(0, 2); // First arguments are the node executable, and the node JS file
|
argv.splice(0, 2); // First arguments are the node executable, and the node JS file
|
||||||
|
|
||||||
while (argv.length) {
|
while (argv.length) {
|
||||||
let arg = argv[0];
|
const arg = argv[0];
|
||||||
let nextArg = argv.length >= 2 ? argv[1] : null;
|
const nextArg = argv.length >= 2 ? argv[1] : null;
|
||||||
|
|
||||||
if (arg == '--profile') {
|
if (arg == '--profile') {
|
||||||
if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError');
|
if (!nextArg) throw new JoplinError(_('Usage: %s', '--profile <dir-path>'), 'flagError');
|
||||||
@ -245,7 +245,7 @@ class BaseApplication {
|
|||||||
|
|
||||||
this.logger().debug('Refreshing notes:', parentType, parentId);
|
this.logger().debug('Refreshing notes:', parentType, parentId);
|
||||||
|
|
||||||
let options = {
|
const options = {
|
||||||
order: stateUtils.notesOrder(state.settings),
|
order: stateUtils.notesOrder(state.settings),
|
||||||
uncompletedTodosOnTop: Setting.value('uncompletedTodosOnTop'),
|
uncompletedTodosOnTop: Setting.value('uncompletedTodosOnTop'),
|
||||||
showCompletedTodos: Setting.value('showCompletedTodos'),
|
showCompletedTodos: Setting.value('showCompletedTodos'),
|
||||||
@ -333,7 +333,7 @@ class BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reducerActionToString(action) {
|
reducerActionToString(action) {
|
||||||
let o = [action.type];
|
const o = [action.type];
|
||||||
if ('id' in action) o.push(action.id);
|
if ('id' in action) o.push(action.id);
|
||||||
if ('noteId' in action) o.push(action.noteId);
|
if ('noteId' in action) o.push(action.noteId);
|
||||||
if ('folderId' in action) o.push(action.folderId);
|
if ('folderId' in action) o.push(action.folderId);
|
||||||
@ -580,7 +580,7 @@ class BaseApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(argv) {
|
async start(argv) {
|
||||||
let startFlags = await this.handleStartFlags_(argv);
|
const startFlags = await this.handleStartFlags_(argv);
|
||||||
|
|
||||||
argv = startFlags.argv;
|
argv = startFlags.argv;
|
||||||
let initArgs = startFlags.matched;
|
let initArgs = startFlags.matched;
|
||||||
@ -712,7 +712,7 @@ class BaseApplication {
|
|||||||
SearchEngine.instance().setLogger(reg.logger());
|
SearchEngine.instance().setLogger(reg.logger());
|
||||||
SearchEngine.instance().scheduleSyncTables();
|
SearchEngine.instance().scheduleSyncTables();
|
||||||
|
|
||||||
let currentFolderId = Setting.value('activeFolderId');
|
const currentFolderId = Setting.value('activeFolderId');
|
||||||
let currentFolder = null;
|
let currentFolder = null;
|
||||||
if (currentFolderId) currentFolder = await Folder.load(currentFolderId);
|
if (currentFolderId) currentFolder = await Folder.load(currentFolderId);
|
||||||
if (!currentFolder) currentFolder = await Folder.defaultFolder();
|
if (!currentFolder) currentFolder = await Folder.defaultFolder();
|
||||||
|
@ -16,7 +16,7 @@ class BaseModel {
|
|||||||
if (!model) return model;
|
if (!model) return model;
|
||||||
|
|
||||||
if (Array.isArray(model)) {
|
if (Array.isArray(model)) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let i = 0; i < model.length; i++) {
|
for (let i = 0; i < model.length; i++) {
|
||||||
output.push(this.addModelMd(model[i]));
|
output.push(this.addModelMd(model[i]));
|
||||||
}
|
}
|
||||||
@ -87,16 +87,16 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static hasField(name) {
|
static hasField(name) {
|
||||||
let fields = this.fieldNames();
|
const fields = this.fieldNames();
|
||||||
return fields.indexOf(name) >= 0;
|
return fields.indexOf(name) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fieldNames(withPrefix = false) {
|
static fieldNames(withPrefix = false) {
|
||||||
let output = this.db().tableFieldNames(this.tableName());
|
const output = this.db().tableFieldNames(this.tableName());
|
||||||
if (!withPrefix) return output;
|
if (!withPrefix) return output;
|
||||||
|
|
||||||
let p = withPrefix === true ? this.tableName() : withPrefix;
|
const p = withPrefix === true ? this.tableName() : withPrefix;
|
||||||
let temp = [];
|
const temp = [];
|
||||||
for (let i = 0; i < output.length; i++) {
|
for (let i = 0; i < output.length; i++) {
|
||||||
temp.push(`${p}.${output[i]}`);
|
temp.push(`${p}.${output[i]}`);
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static fieldType(name, defaultValue = null) {
|
static fieldType(name, defaultValue = null) {
|
||||||
let fields = this.fields();
|
const fields = this.fields();
|
||||||
for (let i = 0; i < fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
if (fields[i].name == name) return fields[i].type;
|
if (fields[i].name == name) return fields[i].type;
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ class BaseModel {
|
|||||||
|
|
||||||
static removeUnknownFields(model) {
|
static removeUnknownFields(model) {
|
||||||
const newModel = {};
|
const newModel = {};
|
||||||
for (let n in model) {
|
for (const n in model) {
|
||||||
if (!model.hasOwnProperty(n)) continue;
|
if (!model.hasOwnProperty(n)) continue;
|
||||||
if (!this.hasField(n) && n !== 'type_') continue;
|
if (!this.hasField(n) && n !== 'type_') continue;
|
||||||
newModel[n] = model[n];
|
newModel[n] = model[n];
|
||||||
@ -128,10 +128,10 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static new() {
|
static new() {
|
||||||
let fields = this.fields();
|
const fields = this.fields();
|
||||||
let output = {};
|
const output = {};
|
||||||
for (let i = 0; i < fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
let f = fields[i];
|
const f = fields[i];
|
||||||
output[f.name] = f.default;
|
output[f.name] = f.default;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
@ -175,7 +175,7 @@ class BaseModel {
|
|||||||
if (!options) options = {};
|
if (!options) options = {};
|
||||||
|
|
||||||
if (options.order && options.order.length) {
|
if (options.order && options.order.length) {
|
||||||
let items = [];
|
const items = [];
|
||||||
for (let i = 0; i < options.order.length; i++) {
|
for (let i = 0; i < options.order.length; i++) {
|
||||||
const o = options.order[i];
|
const o = options.order[i];
|
||||||
let item = o.by;
|
let item = o.by;
|
||||||
@ -192,7 +192,7 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async allIds(options = null) {
|
static async allIds(options = null) {
|
||||||
let q = this.applySqlOptions(options, `SELECT id FROM \`${this.tableName()}\``);
|
const q = this.applySqlOptions(options, `SELECT id FROM \`${this.tableName()}\``);
|
||||||
const rows = await this.db().selectAll(q.sql, q.params);
|
const rows = await this.db().selectAll(q.sql, q.params);
|
||||||
return rows.map(r => r.id);
|
return rows.map(r => r.id);
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ class BaseModel {
|
|||||||
if (options.whereParams) params = params.concat(options.whereParams);
|
if (options.whereParams) params = params.concat(options.whereParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
let q = this.applySqlOptions(options, sql, params);
|
const q = this.applySqlOptions(options, sql, params);
|
||||||
return this.modelSelectAll(q.sql, q.params);
|
return this.modelSelectAll(q.sql, q.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ class BaseModel {
|
|||||||
|
|
||||||
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
|
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
|
||||||
sql += ` WHERE id IN ("${ids.join('","')}")`;
|
sql += ` WHERE id IN ("${ids.join('","')}")`;
|
||||||
let q = this.applySqlOptions(options, sql);
|
const q = this.applySqlOptions(options, sql);
|
||||||
return this.modelSelectAll(q.sql);
|
return this.modelSelectAll(q.sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,11 +227,11 @@ class BaseModel {
|
|||||||
if (!options) options = {};
|
if (!options) options = {};
|
||||||
if (!options.fields) options.fields = '*';
|
if (!options.fields) options.fields = '*';
|
||||||
|
|
||||||
let conditions = options.conditions ? options.conditions.slice(0) : [];
|
const conditions = options.conditions ? options.conditions.slice(0) : [];
|
||||||
let params = options.conditionsParams ? options.conditionsParams.slice(0) : [];
|
const params = options.conditionsParams ? options.conditionsParams.slice(0) : [];
|
||||||
|
|
||||||
if (options.titlePattern) {
|
if (options.titlePattern) {
|
||||||
let pattern = options.titlePattern.replace(/\*/g, '%');
|
const pattern = options.titlePattern.replace(/\*/g, '%');
|
||||||
conditions.push('title LIKE ?');
|
conditions.push('title LIKE ?');
|
||||||
params.push(pattern);
|
params.push(pattern);
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ class BaseModel {
|
|||||||
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
|
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\``;
|
||||||
if (conditions.length) sql += ` WHERE ${conditions.join(' AND ')}`;
|
if (conditions.length) sql += ` WHERE ${conditions.join(' AND ')}`;
|
||||||
|
|
||||||
let query = this.applySqlOptions(options, sql, params);
|
const query = this.applySqlOptions(options, sql, params);
|
||||||
return this.modelSelectAll(query.sql, query.params);
|
return this.modelSelectAll(query.sql, query.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static diffObjects(oldModel, newModel) {
|
static diffObjects(oldModel, newModel) {
|
||||||
let output = {};
|
const output = {};
|
||||||
const fields = this.diffObjectsFields(oldModel, newModel);
|
const fields = this.diffObjectsFields(oldModel, newModel);
|
||||||
for (let i = 0; i < fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
output[fields[i]] = newModel[fields[i]];
|
output[fields[i]] = newModel[fields[i]];
|
||||||
@ -287,8 +287,8 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static diffObjectsFields(oldModel, newModel) {
|
static diffObjectsFields(oldModel, newModel) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let n in newModel) {
|
for (const n in newModel) {
|
||||||
if (!newModel.hasOwnProperty(n)) continue;
|
if (!newModel.hasOwnProperty(n)) continue;
|
||||||
if (n == 'type_') continue;
|
if (n == 'type_') continue;
|
||||||
if (!(n in oldModel) || newModel[n] !== oldModel[n]) {
|
if (!(n in oldModel) || newModel[n] !== oldModel[n]) {
|
||||||
@ -313,7 +313,7 @@ class BaseModel {
|
|||||||
|
|
||||||
if (!modelOrId) return noLockMutex;
|
if (!modelOrId) return noLockMutex;
|
||||||
|
|
||||||
let modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
|
const modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
|
||||||
|
|
||||||
if (!modelId) return noLockMutex;
|
if (!modelId) return noLockMutex;
|
||||||
|
|
||||||
@ -329,11 +329,11 @@ class BaseModel {
|
|||||||
if (!release) return;
|
if (!release) return;
|
||||||
if (!modelOrId) return release();
|
if (!modelOrId) return release();
|
||||||
|
|
||||||
let modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
|
const modelId = typeof modelOrId === 'string' ? modelOrId : modelOrId.id;
|
||||||
|
|
||||||
if (!modelId) return release();
|
if (!modelId) return release();
|
||||||
|
|
||||||
let mutex = BaseModel.saveMutexes_[modelId];
|
const mutex = BaseModel.saveMutexes_[modelId];
|
||||||
if (!mutex) return release();
|
if (!mutex) return release();
|
||||||
|
|
||||||
delete BaseModel.saveMutexes_[modelId];
|
delete BaseModel.saveMutexes_[modelId];
|
||||||
@ -342,9 +342,9 @@ class BaseModel {
|
|||||||
|
|
||||||
static saveQuery(o, options) {
|
static saveQuery(o, options) {
|
||||||
let temp = {};
|
let temp = {};
|
||||||
let fieldNames = this.fieldNames();
|
const fieldNames = this.fieldNames();
|
||||||
for (let i = 0; i < fieldNames.length; i++) {
|
for (let i = 0; i < fieldNames.length; i++) {
|
||||||
let n = fieldNames[i];
|
const n = fieldNames[i];
|
||||||
if (n in o) temp[n] = o[n];
|
if (n in o) temp[n] = o[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ class BaseModel {
|
|||||||
// id also will stay.
|
// id also will stay.
|
||||||
if (!options.isNew && options.fields) {
|
if (!options.isNew && options.fields) {
|
||||||
const filtered = {};
|
const filtered = {};
|
||||||
for (let k in temp) {
|
for (const k in temp) {
|
||||||
if (!temp.hasOwnProperty(k)) continue;
|
if (!temp.hasOwnProperty(k)) continue;
|
||||||
if (k !== 'id' && options.fields.indexOf(k) < 0) continue;
|
if (k !== 'id' && options.fields.indexOf(k) < 0) continue;
|
||||||
filtered[k] = temp[k];
|
filtered[k] = temp[k];
|
||||||
@ -404,8 +404,8 @@ class BaseModel {
|
|||||||
|
|
||||||
query = Database.insertQuery(this.tableName(), o);
|
query = Database.insertQuery(this.tableName(), o);
|
||||||
} else {
|
} else {
|
||||||
let where = { id: o.id };
|
const where = { id: o.id };
|
||||||
let temp = Object.assign({}, o);
|
const temp = Object.assign({}, o);
|
||||||
delete temp.id;
|
delete temp.id;
|
||||||
|
|
||||||
query = Database.updateQuery(this.tableName(), temp, where);
|
query = Database.updateQuery(this.tableName(), temp, where);
|
||||||
@ -445,8 +445,8 @@ class BaseModel {
|
|||||||
o = this.filter(o);
|
o = this.filter(o);
|
||||||
|
|
||||||
let queries = [];
|
let queries = [];
|
||||||
let saveQuery = this.saveQuery(o, options);
|
const saveQuery = this.saveQuery(o, options);
|
||||||
let modelId = saveQuery.id;
|
const modelId = saveQuery.id;
|
||||||
|
|
||||||
queries.push(saveQuery);
|
queries.push(saveQuery);
|
||||||
|
|
||||||
@ -473,7 +473,7 @@ class BaseModel {
|
|||||||
o = this.addModelMd(o);
|
o = this.addModelMd(o);
|
||||||
|
|
||||||
if (isDiffSaving) {
|
if (isDiffSaving) {
|
||||||
for (let n in options.oldItem) {
|
for (const n in options.oldItem) {
|
||||||
if (!options.oldItem.hasOwnProperty(n)) continue;
|
if (!options.oldItem.hasOwnProperty(n)) continue;
|
||||||
if (n in o) continue;
|
if (n in o) continue;
|
||||||
o[n] = options.oldItem[n];
|
o[n] = options.oldItem[n];
|
||||||
@ -499,7 +499,7 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static filterArray(models) {
|
static filterArray(models) {
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let i = 0; i < models.length; i++) {
|
for (let i = 0; i < models.length; i++) {
|
||||||
output.push(this.filter(models[i]));
|
output.push(this.filter(models[i]));
|
||||||
}
|
}
|
||||||
@ -509,8 +509,8 @@ class BaseModel {
|
|||||||
static filter(model) {
|
static filter(model) {
|
||||||
if (!model) return model;
|
if (!model) return model;
|
||||||
|
|
||||||
let output = Object.assign({}, model);
|
const output = Object.assign({}, model);
|
||||||
for (let n in output) {
|
for (const n in output) {
|
||||||
if (!output.hasOwnProperty(n)) continue;
|
if (!output.hasOwnProperty(n)) continue;
|
||||||
|
|
||||||
// The SQLite database doesn't have booleans so cast everything to int
|
// The SQLite database doesn't have booleans so cast everything to int
|
||||||
|
@ -51,11 +51,11 @@ class DropboxApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestToCurl_(url, options) {
|
requestToCurl_(url, options) {
|
||||||
let output = [];
|
const output = [];
|
||||||
output.push('curl');
|
output.push('curl');
|
||||||
if (options.method) output.push(`-X ${options.method}`);
|
if (options.method) output.push(`-X ${options.method}`);
|
||||||
if (options.headers) {
|
if (options.headers) {
|
||||||
for (let n in options.headers) {
|
for (const n in options.headers) {
|
||||||
if (!options.headers.hasOwnProperty(n)) continue;
|
if (!options.headers.hasOwnProperty(n)) continue;
|
||||||
output.push(`${'-H ' + '\''}${n}: ${options.headers[n]}'`);
|
output.push(`${'-H ' + '\''}${n}: ${options.headers[n]}'`);
|
||||||
}
|
}
|
||||||
@ -74,10 +74,10 @@ class DropboxApi {
|
|||||||
client_secret: this.clientSecret(),
|
client_secret: this.clientSecret(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var formBody = [];
|
let formBody = [];
|
||||||
for (var property in postData) {
|
for (const property in postData) {
|
||||||
var encodedKey = encodeURIComponent(property);
|
const encodedKey = encodeURIComponent(property);
|
||||||
var encodedValue = encodeURIComponent(postData[property]);
|
const encodedValue = encodeURIComponent(postData[property]);
|
||||||
formBody.push(`${encodedKey}=${encodedValue}`);
|
formBody.push(`${encodedKey}=${encodedValue}`);
|
||||||
}
|
}
|
||||||
formBody = formBody.join('&');
|
formBody = formBody.join('&');
|
||||||
|
@ -6,7 +6,7 @@ class EventDispatcher {
|
|||||||
dispatch(eventName, event = null) {
|
dispatch(eventName, event = null) {
|
||||||
if (!this.listeners_[eventName]) return;
|
if (!this.listeners_[eventName]) return;
|
||||||
|
|
||||||
let ls = this.listeners_[eventName];
|
const ls = this.listeners_[eventName];
|
||||||
for (let i = 0; i < ls.length; i++) {
|
for (let i = 0; i < ls.length; i++) {
|
||||||
ls[i](event);
|
ls[i](event);
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class EventDispatcher {
|
|||||||
off(eventName, callback) {
|
off(eventName, callback) {
|
||||||
if (!this.listeners_[eventName]) return;
|
if (!this.listeners_[eventName]) return;
|
||||||
|
|
||||||
let ls = this.listeners_[eventName];
|
const ls = this.listeners_[eventName];
|
||||||
for (let i = 0; i < ls.length; i++) {
|
for (let i = 0; i < ls.length; i++) {
|
||||||
if (ls[i] === callback) {
|
if (ls[i] === callback) {
|
||||||
ls.splice(i, 1);
|
ls.splice(i, 1);
|
||||||
|
@ -83,12 +83,12 @@ export default class JoplinServerApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestToCurl_(url:string, options:any) {
|
requestToCurl_(url:string, options:any) {
|
||||||
let output = [];
|
const output = [];
|
||||||
output.push('curl');
|
output.push('curl');
|
||||||
output.push('-v');
|
output.push('-v');
|
||||||
if (options.method) output.push(`-X ${options.method}`);
|
if (options.method) output.push(`-X ${options.method}`);
|
||||||
if (options.headers) {
|
if (options.headers) {
|
||||||
for (let n in options.headers) {
|
for (const n in options.headers) {
|
||||||
if (!options.headers.hasOwnProperty(n)) continue;
|
if (!options.headers.hasOwnProperty(n)) continue;
|
||||||
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
|
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ export default class JoplinServerApi {
|
|||||||
|
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
|
|
||||||
let responseJson_:any = null;
|
const responseJson_:any = null;
|
||||||
const loadResponseJson = async () => {
|
const loadResponseJson = async () => {
|
||||||
if (!responseText) return null;
|
if (!responseText) return null;
|
||||||
if (responseJson_) return responseJson_;
|
if (responseJson_) return responseJson_;
|
||||||
|
@ -2,7 +2,7 @@ const ObjectUtils = {};
|
|||||||
|
|
||||||
ObjectUtils.sortByValue = function(object) {
|
ObjectUtils.sortByValue = function(object) {
|
||||||
const temp = [];
|
const temp = [];
|
||||||
for (let k in object) {
|
for (const k in object) {
|
||||||
if (!object.hasOwnProperty(k)) continue;
|
if (!object.hasOwnProperty(k)) continue;
|
||||||
temp.push({
|
temp.push({
|
||||||
key: k,
|
key: k,
|
||||||
@ -31,7 +31,7 @@ ObjectUtils.sortByValue = function(object) {
|
|||||||
ObjectUtils.fieldsEqual = function(o1, o2) {
|
ObjectUtils.fieldsEqual = function(o1, o2) {
|
||||||
if ((!o1 || !o2) && o1 !== o2) return false;
|
if ((!o1 || !o2) && o1 !== o2) return false;
|
||||||
|
|
||||||
for (let k in o1) {
|
for (const k in o1) {
|
||||||
if (!o1.hasOwnProperty(k)) continue;
|
if (!o1.hasOwnProperty(k)) continue;
|
||||||
if (o1[k] !== o2[k]) return false;
|
if (o1[k] !== o2[k]) return false;
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ ObjectUtils.fieldsEqual = function(o1, o2) {
|
|||||||
|
|
||||||
ObjectUtils.convertValuesToFunctions = function(o) {
|
ObjectUtils.convertValuesToFunctions = function(o) {
|
||||||
const output = {};
|
const output = {};
|
||||||
for (let n in o) {
|
for (const n in o) {
|
||||||
if (!o.hasOwnProperty(n)) continue;
|
if (!o.hasOwnProperty(n)) continue;
|
||||||
output[n] = () => {
|
output[n] = () => {
|
||||||
return typeof o[n] === 'function' ? o[n]() : o[n];
|
return typeof o[n] === 'function' ? o[n]() : o[n];
|
||||||
|
@ -16,7 +16,7 @@ class SyncTargetRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nameToId(name) {
|
static nameToId(name) {
|
||||||
for (let n in this.reg_) {
|
for (const n in this.reg_) {
|
||||||
if (!this.reg_.hasOwnProperty(n)) continue;
|
if (!this.reg_.hasOwnProperty(n)) continue;
|
||||||
if (this.reg_[n].name === name) return this.reg_[n].id;
|
if (this.reg_[n].name === name) return this.reg_[n].id;
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ class SyncTargetRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static idToMetadata(id) {
|
static idToMetadata(id) {
|
||||||
for (let n in this.reg_) {
|
for (const n in this.reg_) {
|
||||||
if (!this.reg_.hasOwnProperty(n)) continue;
|
if (!this.reg_.hasOwnProperty(n)) continue;
|
||||||
if (this.reg_[n].id === id) return this.reg_[n];
|
if (this.reg_[n].id === id) return this.reg_[n];
|
||||||
}
|
}
|
||||||
@ -36,8 +36,8 @@ class SyncTargetRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static idAndLabelPlainObject(os) {
|
static idAndLabelPlainObject(os) {
|
||||||
let output = {};
|
const output = {};
|
||||||
for (let n in this.reg_) {
|
for (const n in this.reg_) {
|
||||||
if (!this.reg_.hasOwnProperty(n)) continue;
|
if (!this.reg_.hasOwnProperty(n)) continue;
|
||||||
const info = this.reg_[n];
|
const info = this.reg_[n];
|
||||||
if (info.classRef.unsupportedPlatforms().indexOf(os) >= 0) {
|
if (info.classRef.unsupportedPlatforms().indexOf(os) >= 0) {
|
||||||
|
@ -30,7 +30,7 @@ TemplateUtils.render = function(input) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TemplateUtils.loadTemplates = async function(filePath) {
|
TemplateUtils.loadTemplates = async function(filePath) {
|
||||||
let templates = [];
|
const templates = [];
|
||||||
let files = [];
|
let files = [];
|
||||||
|
|
||||||
if (await shim.fsDriver().exists(filePath)) {
|
if (await shim.fsDriver().exists(filePath)) {
|
||||||
@ -50,7 +50,7 @@ TemplateUtils.loadTemplates = async function(filePath) {
|
|||||||
files.forEach(async file => {
|
files.forEach(async file => {
|
||||||
if (file.path.endsWith('.md')) {
|
if (file.path.endsWith('.md')) {
|
||||||
try {
|
try {
|
||||||
let fileString = await shim.fsDriver().readFile(`${filePath}/${file.path}`, 'utf-8');
|
const fileString = await shim.fsDriver().readFile(`${filePath}/${file.path}`, 'utf-8');
|
||||||
templates.push({ label: file.path, value: fileString });
|
templates.push({ label: file.path, value: fileString });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let msg = error.message ? error.message : '';
|
let msg = error.message ? error.message : '';
|
||||||
|
@ -83,7 +83,7 @@ class WebDavApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async xmlToJson(xml) {
|
async xmlToJson(xml) {
|
||||||
let davNamespaces = []; // Yes, there can be more than one... xmlns:a="DAV:" xmlns:D="DAV:"
|
const davNamespaces = []; // Yes, there can be more than one... xmlns:a="DAV:" xmlns:D="DAV:"
|
||||||
|
|
||||||
const nameProcessor = name => {
|
const nameProcessor = name => {
|
||||||
if (name.indexOf('xmlns') !== 0) {
|
if (name.indexOf('xmlns') !== 0) {
|
||||||
@ -247,12 +247,12 @@ class WebDavApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestToCurl_(url, options) {
|
requestToCurl_(url, options) {
|
||||||
let output = [];
|
const output = [];
|
||||||
output.push('curl');
|
output.push('curl');
|
||||||
output.push('-v');
|
output.push('-v');
|
||||||
if (options.method) output.push(`-X ${options.method}`);
|
if (options.method) output.push(`-X ${options.method}`);
|
||||||
if (options.headers) {
|
if (options.headers) {
|
||||||
for (let n in options.headers) {
|
for (const n in options.headers) {
|
||||||
if (!options.headers.hasOwnProperty(n)) continue;
|
if (!options.headers.hasOwnProperty(n)) continue;
|
||||||
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
|
output.push(`${'-H ' + '"'}${n}: ${options.headers[n]}"`);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class WelcomeUtils {
|
|||||||
|
|
||||||
let noteBody = noteAsset.body;
|
let noteBody = noteAsset.body;
|
||||||
|
|
||||||
for (let resourceUrl in noteAsset.resources) {
|
for (const resourceUrl in noteAsset.resources) {
|
||||||
if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue;
|
if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue;
|
||||||
const resourceAsset = noteAsset.resources[resourceUrl];
|
const resourceAsset = noteAsset.resources[resourceUrl];
|
||||||
const ext = fileExtension(resourceUrl);
|
const ext = fileExtension(resourceUrl);
|
||||||
|
@ -107,10 +107,10 @@ class CameraView extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fitRectIntoBounds(rect, bounds) {
|
fitRectIntoBounds(rect, bounds) {
|
||||||
var rectRatio = rect.width / rect.height;
|
const rectRatio = rect.width / rect.height;
|
||||||
var boundsRatio = bounds.width / bounds.height;
|
const boundsRatio = bounds.width / bounds.height;
|
||||||
|
|
||||||
var newDimensions = {};
|
const newDimensions = {};
|
||||||
|
|
||||||
// Rect is more landscape than bounds - fit to width
|
// Rect is more landscape than bounds - fit to width
|
||||||
if (rectRatio > boundsRatio) {
|
if (rectRatio > boundsRatio) {
|
||||||
|
@ -16,7 +16,7 @@ class ModalDialog extends React.Component {
|
|||||||
if (this.styles_[themeId]) return this.styles_[themeId];
|
if (this.styles_[themeId]) return this.styles_[themeId];
|
||||||
this.styles_ = {};
|
this.styles_ = {};
|
||||||
|
|
||||||
let styles = {
|
const styles = {
|
||||||
modalWrapper: {
|
modalWrapper: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -56,7 +56,7 @@ class ActionButtonComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let buttons = this.props.buttons ? this.props.buttons : [];
|
const buttons = this.props.buttons ? this.props.buttons : [];
|
||||||
|
|
||||||
if (this.props.addFolderNoteButtons) {
|
if (this.props.addFolderNoteButtons) {
|
||||||
if (this.props.folders.length) {
|
if (this.props.folders.length) {
|
||||||
@ -80,11 +80,11 @@ class ActionButtonComponent extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttonComps = [];
|
const buttonComps = [];
|
||||||
for (let i = 0; i < buttons.length; i++) {
|
for (let i = 0; i < buttons.length; i++) {
|
||||||
let button = buttons[i];
|
const button = buttons[i];
|
||||||
let buttonTitle = button.title ? button.title : '';
|
const buttonTitle = button.title ? button.title : '';
|
||||||
let key = `${buttonTitle.replace(/\s/g, '_')}_${button.icon}`;
|
const key = `${buttonTitle.replace(/\s/g, '_')}_${button.icon}`;
|
||||||
buttonComps.push(
|
buttonComps.push(
|
||||||
<ReactNativeActionButton.Item key={key} buttonColor={button.color} title={buttonTitle} onPress={button.onPress}>
|
<ReactNativeActionButton.Item key={key} buttonColor={button.color} title={buttonTitle} onPress={button.onPress}>
|
||||||
<Icon name={button.icon} style={styles.actionButtonIcon} />
|
<Icon name={button.icon} style={styles.actionButtonIcon} />
|
||||||
@ -96,14 +96,14 @@ class ActionButtonComponent extends React.Component {
|
|||||||
return <ReactNativeActionButton style={{ display: 'none' }} />;
|
return <ReactNativeActionButton style={{ display: 'none' }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mainButton = this.props.mainButton ? this.props.mainButton : {};
|
const mainButton = this.props.mainButton ? this.props.mainButton : {};
|
||||||
let mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Icon name="md-add" style={styles.actionButtonIcon} />;
|
const mainIcon = mainButton.icon ? <Icon name={mainButton.icon} style={styles.actionButtonIcon} /> : <Icon name="md-add" style={styles.actionButtonIcon} />;
|
||||||
|
|
||||||
if (this.props.multiStates) {
|
if (this.props.multiStates) {
|
||||||
if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state');
|
if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state');
|
||||||
if (this.state.buttonIndex < 0 || this.state.buttonIndex >= this.props.buttons.length) throw new Error(`Button index out of bounds: ${this.state.buttonIndex}/${this.props.buttons.length}`);
|
if (this.state.buttonIndex < 0 || this.state.buttonIndex >= this.props.buttons.length) throw new Error(`Button index out of bounds: ${this.state.buttonIndex}/${this.props.buttons.length}`);
|
||||||
let button = this.props.buttons[this.state.buttonIndex];
|
const button = this.props.buttons[this.state.buttonIndex];
|
||||||
let mainIcon = <Icon name={button.icon} style={styles.actionButtonIcon} />;
|
const mainIcon = <Icon name={button.icon} style={styles.actionButtonIcon} />;
|
||||||
return (
|
return (
|
||||||
<ReactNativeActionButton
|
<ReactNativeActionButton
|
||||||
icon={mainIcon}
|
icon={mainIcon}
|
||||||
|
@ -43,7 +43,7 @@ class AppNavComponent extends Component {
|
|||||||
// Note: certain screens are kept into memory, in particular Notes and Search
|
// Note: certain screens are kept into memory, in particular Notes and Search
|
||||||
// so that the scroll position is not lost when the user navigate away from them.
|
// so that the scroll position is not lost when the user navigate away from them.
|
||||||
|
|
||||||
let route = this.props.route;
|
const route = this.props.route;
|
||||||
let Screen = null;
|
let Screen = null;
|
||||||
let notesScreenVisible = false;
|
let notesScreenVisible = false;
|
||||||
let searchScreenVisible = false;
|
let searchScreenVisible = false;
|
||||||
@ -59,7 +59,7 @@ class AppNavComponent extends Component {
|
|||||||
// Keep the search screen loaded if the user is viewing a note from that search screen
|
// Keep the search screen loaded if the user is viewing a note from that search screen
|
||||||
// so that if the back button is pressed, the screen is still loaded. However, unload
|
// so that if the back button is pressed, the screen is still loaded. However, unload
|
||||||
// it if navigating away.
|
// it if navigating away.
|
||||||
let searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ == 'Search' && route.routeName == 'Note');
|
const searchScreenLoaded = searchScreenVisible || (this.previousRouteName_ == 'Search' && route.routeName == 'Note');
|
||||||
|
|
||||||
this.previousRouteName_ = route.routeName;
|
this.previousRouteName_ = route.routeName;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ const styleObject_ = {
|
|||||||
|
|
||||||
const styles_ = StyleSheet.create(styleObject_);
|
const styles_ = StyleSheet.create(styleObject_);
|
||||||
|
|
||||||
let rootStyles_ = {};
|
const rootStyles_ = {};
|
||||||
|
|
||||||
class BaseScreenComponent extends React.Component {
|
class BaseScreenComponent extends React.Component {
|
||||||
styles() {
|
styles() {
|
||||||
|
@ -31,7 +31,7 @@ class Checkbox extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPress() {
|
onPress() {
|
||||||
let newChecked = !this.state.checked;
|
const newChecked = !this.state.checked;
|
||||||
this.setState({ checked: newChecked });
|
this.setState({ checked: newChecked });
|
||||||
if (this.props.onChange) this.props.onChange(newChecked);
|
if (this.props.onChange) this.props.onChange(newChecked);
|
||||||
}
|
}
|
||||||
@ -39,11 +39,11 @@ class Checkbox extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline';
|
const iconName = this.state.checked ? 'md-checkbox-outline' : 'md-square-outline';
|
||||||
|
|
||||||
let style = this.props.style ? Object.assign({}, this.props.style) : {};
|
const style = this.props.style ? Object.assign({}, this.props.style) : {};
|
||||||
style.justifyContent = 'center';
|
style.justifyContent = 'center';
|
||||||
style.alignItems = 'center';
|
style.alignItems = 'center';
|
||||||
|
|
||||||
let checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
|
const checkboxIconStyle = Object.assign({}, styles.checkboxIcon);
|
||||||
if (style.color) checkboxIconStyle.color = style.color;
|
if (style.color) checkboxIconStyle.color = style.color;
|
||||||
|
|
||||||
if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop;
|
if (style.paddingTop) checkboxIconStyle.marginTop = style.paddingTop;
|
||||||
|
@ -47,7 +47,7 @@ globalStyle.marginTop = globalStyle.margin;
|
|||||||
globalStyle.marginBottom = globalStyle.margin;
|
globalStyle.marginBottom = globalStyle.margin;
|
||||||
globalStyle.htmlMarginLeft = `${((globalStyle.marginLeft / 10) * 0.6).toFixed(2)}em`;
|
globalStyle.htmlMarginLeft = `${((globalStyle.marginLeft / 10) * 0.6).toFixed(2)}em`;
|
||||||
|
|
||||||
let themeCache_ = {};
|
const themeCache_ = {};
|
||||||
|
|
||||||
function addExtraStyles(style) {
|
function addExtraStyles(style) {
|
||||||
style.icon = {
|
style.icon = {
|
||||||
@ -122,7 +122,7 @@ function themeStyle(theme) {
|
|||||||
|
|
||||||
if (themeCache_[theme]) return themeCache_[theme];
|
if (themeCache_[theme]) return themeCache_[theme];
|
||||||
|
|
||||||
let output = Object.assign({}, globalStyle);
|
const output = Object.assign({}, globalStyle);
|
||||||
if (theme == Setting.THEME_LIGHT) return addExtraStyles(output);
|
if (theme == Setting.THEME_LIGHT) return addExtraStyles(output);
|
||||||
else if (theme == Setting.THEME_OLED_DARK) {
|
else if (theme == Setting.THEME_OLED_DARK) {
|
||||||
output.backgroundColor = '#000000';
|
output.backgroundColor = '#000000';
|
||||||
|
@ -62,7 +62,7 @@ class NoteBodyViewer extends Component {
|
|||||||
postMessageSyntax: 'window.ReactNativeWebView.postMessage',
|
postMessageSyntax: 'window.ReactNativeWebView.postMessage',
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = await this.markupToHtml_.render(note.markup_language, bodyToRender, this.props.webViewStyle, mdOptions);
|
const result = await this.markupToHtml_.render(note.markup_language, bodyToRender, this.props.webViewStyle, mdOptions);
|
||||||
let html = result.html;
|
let html = result.html;
|
||||||
|
|
||||||
const resourceDownloadMode = Setting.value('sync.resourceDownloadMode');
|
const resourceDownloadMode = Setting.value('sync.resourceDownloadMode');
|
||||||
@ -188,7 +188,7 @@ class NoteBodyViewer extends Component {
|
|||||||
// https://github.com/react-native-community/react-native-webview/issues/312#issuecomment-503754654
|
// https://github.com/react-native-community/react-native-webview/issues/312#issuecomment-503754654
|
||||||
|
|
||||||
|
|
||||||
let webViewStyle = { backgroundColor: this.props.webViewStyle.backgroundColor };
|
const webViewStyle = { backgroundColor: this.props.webViewStyle.backgroundColor };
|
||||||
// On iOS, the onLoadEnd() event is never fired so always
|
// On iOS, the onLoadEnd() event is never fired so always
|
||||||
// display the webview (don't do the little trick
|
// display the webview (don't do the little trick
|
||||||
// to avoid the white flash).
|
// to avoid the white flash).
|
||||||
|
@ -27,7 +27,7 @@ class NoteItemComponent extends Component {
|
|||||||
if (this.styles_[this.props.theme]) return this.styles_[this.props.theme];
|
if (this.styles_[this.props.theme]) return this.styles_[this.props.theme];
|
||||||
this.styles_ = {};
|
this.styles_ = {};
|
||||||
|
|
||||||
let styles = {
|
const styles = {
|
||||||
listItem: {
|
listItem: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
// height: 40,
|
// height: 40,
|
||||||
@ -110,7 +110,7 @@ class NoteItemComponent extends Component {
|
|||||||
const theme = themeStyle(this.props.theme);
|
const theme = themeStyle(this.props.theme);
|
||||||
|
|
||||||
// IOS: display: none crashes the app
|
// IOS: display: none crashes the app
|
||||||
let checkboxStyle = !isTodo ? { display: 'none' } : { color: theme.color };
|
const checkboxStyle = !isTodo ? { display: 'none' } : { color: theme.color };
|
||||||
|
|
||||||
if (isTodo) {
|
if (isTodo) {
|
||||||
checkboxStyle.paddingRight = 10;
|
checkboxStyle.paddingRight = 10;
|
||||||
|
@ -28,7 +28,7 @@ class NoteListComponent extends Component {
|
|||||||
if (this.styles_[themeId]) return this.styles_[themeId];
|
if (this.styles_[themeId]) return this.styles_[themeId];
|
||||||
this.styles_ = {};
|
this.styles_ = {};
|
||||||
|
|
||||||
let styles = {
|
const styles = {
|
||||||
noItemMessage: {
|
noItemMessage: {
|
||||||
paddingLeft: theme.marginLeft,
|
paddingLeft: theme.marginLeft,
|
||||||
paddingRight: theme.marginRight,
|
paddingRight: theme.marginRight,
|
||||||
@ -63,7 +63,7 @@ class NoteListComponent extends Component {
|
|||||||
const maxInterval = 1000 * 60 * 60 * 24;
|
const maxInterval = 1000 * 60 * 60 * 24;
|
||||||
const notRecentTime = now - maxInterval;
|
const notRecentTime = now - maxInterval;
|
||||||
|
|
||||||
let output = [];
|
const output = [];
|
||||||
for (let i = 0; i < notes.length; i++) {
|
for (let i = 0; i < notes.length; i++) {
|
||||||
const note = notes[i];
|
const note = notes[i];
|
||||||
if (note.is_todo) {
|
if (note.is_todo) {
|
||||||
|
@ -36,7 +36,7 @@ class ScreenHeaderComponent extends React.PureComponent {
|
|||||||
|
|
||||||
const theme = themeStyle(themeId);
|
const theme = themeStyle(themeId);
|
||||||
|
|
||||||
let styleObject = {
|
const styleObject = {
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
backgroundColor: theme.raisedBackgroundColor,
|
backgroundColor: theme.raisedBackgroundColor,
|
||||||
@ -299,11 +299,11 @@ class ScreenHeaderComponent extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let key = 0;
|
let key = 0;
|
||||||
let menuOptionComponents = [];
|
const menuOptionComponents = [];
|
||||||
|
|
||||||
if (!this.props.noteSelectionEnabled) {
|
if (!this.props.noteSelectionEnabled) {
|
||||||
for (let i = 0; i < this.props.menuOptions.length; i++) {
|
for (let i = 0; i < this.props.menuOptions.length; i++) {
|
||||||
let o = this.props.menuOptions[i];
|
const o = this.props.menuOptions[i];
|
||||||
|
|
||||||
if (o.isDivider) {
|
if (o.isDivider) {
|
||||||
menuOptionComponents.push(<View key={`menuOption_${key++}`} style={this.styles().divider} />);
|
menuOptionComponents.push(<View key={`menuOption_${key++}`} style={this.styles().divider} />);
|
||||||
@ -408,7 +408,7 @@ class ScreenHeaderComponent extends React.PureComponent {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let title = 'title' in this.props && this.props.title !== null ? this.props.title : '';
|
const title = 'title' in this.props && this.props.title !== null ? this.props.title : '';
|
||||||
return <Text style={this.styles().titleText}>{title}</Text>;
|
return <Text style={this.styles().titleText}>{title}</Text>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -122,7 +122,7 @@ class NoteTagsDialogComponent extends React.Component {
|
|||||||
if (this.styles_[themeId]) return this.styles_[themeId];
|
if (this.styles_[themeId]) return this.styles_[themeId];
|
||||||
this.styles_ = {};
|
this.styles_ = {};
|
||||||
|
|
||||||
let styles = {
|
const styles = {
|
||||||
tag: {
|
tag: {
|
||||||
padding: 10,
|
padding: 10,
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user