1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-13 22:12:50 +02:00

Improve browsing of notes

This commit is contained in:
Laurent Cozic
2017-06-25 10:00:54 +01:00
parent 79e0bb2e65
commit cf494cfd17
5 changed files with 83 additions and 27 deletions

View File

@@ -196,18 +196,13 @@ async function main() {
usage: 'use <notebook-title>',
aliases: ['cd'],
description: 'Switches to [notebook-title] - all further operations will happen within this notebook.',
action: function(args, end) {
action: async function(args, end) {
let folderTitle = args['notebook-title'];
if (folderTitle == '.' || folderTitle == '..') {
end();
return;
}
Folder.loadByField('title', folderTitle).then((folder) => {
let folder = await Folder.loadByField('title', folderTitle);
if (!folder) return commandError(this, _('Invalid folder title: %s', folderTitle), end);
switchCurrentFolder(folder);
end();
});
},
autocomplete: autocompleteFolders,
});
@@ -355,14 +350,32 @@ async function main() {
description: 'Displays the notes in [notebook-title]. Use `ls ..` to display the list of notebooks.',
options: [
['-n, --lines <num>', 'Displays only the first top <num> lines.'],
['-s, --sort <field>', 'Sorts the item by <field> (eg. title, updated_time, created_time).'],
['-r, --reverse', 'Reverses the sorting order.'],
['-t, --type <type>', 'Displays only the items of the specific type(s). Can be `n` for notes, `t` for todos, or `nt` for notes and todos (eg. `-tt` would display only the todos, while `-ttd` would display notes and todos.'],
],
action: async function(args, end) {
let folderTitle = args['notebook-title'];
let suffix = '';
let items = [];
let options = args.options;
let queryOptions = {};
if (options.lines) queryOptions.limit = options.lines;
if (options.sort) {
queryOptions.orderBy = options.sort;
queryOptions.orderByDir = 'ASC';
}
if (options.reverse === true) queryOptions.orderByDir = queryOptions.orderByDir == 'ASC' ? 'DESC' : 'ASC';
queryOptions.caseInsensitive = true;
if (options.type) {
queryOptions.itemTypes = [];
if (options.type.indexOf('n') >= 0) queryOptions.itemTypes.push('note');
if (options.type.indexOf('t') >= 0) queryOptions.itemTypes.push('todo');
}
if (folderTitle == '..') {
items = await Folder.all();
items = await Folder.all(queryOptions);
suffix = '/';
} else {
let folder = null;
@@ -375,12 +388,17 @@ async function main() {
if (!folder) return commandError(this, _('Unknown notebook: "%s"', folderTitle), end);
items = await Note.previews(folder.id);
items = await Note.previews(folder.id, queryOptions);
}
for (let i = 0; i < items.length; i++) {
let item = items[i];
this.log(item.title + suffix);
let line = '';
if (!!item.is_todo) {
line += sprintf('[%s] ', !!item.todo_completed ? 'X' : ' ');
}
line += item.title + suffix;
this.log(line);
}
end();

View File

@@ -46,7 +46,7 @@ describe('Synchronizer', function() {
let folder = await Folder.save({ title: "folder1" });
await Note.save({ title: "un", parent_id: folder.id });
let all = await Folder.all(true);
let all = await Folder.all({ includeNotes: true });
await synchronizer().start();
@@ -64,7 +64,7 @@ describe('Synchronizer', function() {
await Note.save({ title: "un UPDATE", id: note.id });
let all = await Folder.all(true);
let all = await Folder.all({ includeNotes: true });
await synchronizer().start();
await localItemsSameAsRemote(all, expect);
@@ -81,7 +81,7 @@ describe('Synchronizer', function() {
await synchronizer().start();
let all = await Folder.all(true);
let all = await Folder.all({ includeNotes: true });
await localItemsSameAsRemote(all, expect);
done();
@@ -109,7 +109,7 @@ describe('Synchronizer', function() {
await synchronizer().start();
let all = await Folder.all(true);
let all = await Folder.all({ includeNotes: true });
let files = await fileApi().list();
await localItemsSameAsRemote(all, expect);
@@ -250,7 +250,7 @@ describe('Synchronizer', function() {
await synchronizer().start();
let items = await Folder.all(true);
let items = await Folder.all({ includeNotes: true });
expect(items.length).toBe(1);
@@ -288,7 +288,7 @@ describe('Synchronizer', function() {
expect(conflictedNotes.length).toBe(1);
expect(conflictedNotes[0].title).toBe(newTitle);
let items = await Folder.all(true);
let items = await Folder.all({ includeNotes: true });
expect(items.length).toBe(1);
@@ -319,7 +319,7 @@ describe('Synchronizer', function() {
await synchronizer().start();
let items = await Folder.all(true);
let items = await Folder.all({ includeNotes: true });
expect(items.length).toBe(0);

View File

@@ -120,6 +120,24 @@ class BaseModel {
return this.loadByField('id', id);
}
static applySqlOptions(options, sql, params = null) {
if (!options) options = {};
if (options.orderBy) {
sql += ' ORDER BY ' + options.orderBy;
if (options.caseInsensitive === true) sql += ' COLLATE NOCASE';
if (options.orderByDir) sql += ' ' + options.orderByDir;
}
if (options.limit) sql += ' LIMIT ' + options.limit;
return { sql: sql, params: params };
}
static async all(options = null) {
let q = this.applySqlOptions(options, 'SELECT * FROM `' + this.tableName() + '`');
return await this.modelSelectAll(q.sql);
}
static modelSelectOne(sql, params = null) {
if (params === null) params = [];
return this.db().selectOne(sql, params).then((model) => {

View File

@@ -81,11 +81,15 @@ class Folder extends BaseItem {
return this.modelSelectOne('SELECT * FROM notes WHERE is_conflict = 0 AND `parent_id` = ? AND `' + field + '` = ?', [folderId, value]);
}
static async all(includeNotes = false) {
let folders = await Folder.modelSelectAll('SELECT * FROM folders');
if (!includeNotes) return folders;
static async all(options = null) {
if (!options) options = {};
let notes = await Note.modelSelectAll('SELECT * FROM notes WHERE is_conflict = 0');
let folders = await super.all(options);
if (!options.includeNotes) return folders;
if (options.limit) options.limit -= folders.length;
let notes = await Note.all(options);
return folders.concat(notes);
}

View File

@@ -43,8 +43,24 @@ class Note extends BaseItem {
return '`id`, `title`, `body`, `is_todo`, `todo_completed`, `parent_id`, `updated_time`'
}
static previews(parentId) {
return this.modelSelectAll('SELECT ' + this.previewFieldsSql() + ' FROM notes WHERE is_conflict = 0 AND parent_id = ?', [parentId]);
static previews(parentId, options = null) {
if (!options) options = {};
if (!options.orderBy) options.orderBy = 'updated_time';
if (!options.orderByDir) options.orderByDir = 'DESC';
let sql = 'SELECT ' + this.previewFieldsSql() + ' FROM notes WHERE is_conflict = 0 AND parent_id = ?';
if (options.itemTypes && options.itemTypes.length) {
if (options.itemTypes.indexOf('note') >= 0 && options.itemTypes.indexOf('todo') >= 0) {
// Fetch everything
} else if (options.itemTypes.indexOf('note') >= 0) {
sql += ' AND is_todo = 0';
} else if (options.itemTypes.indexOf('todo') >= 0) {
sql += ' AND is_todo = 1';
}
}
let query = this.applySqlOptions(options, sql, [parentId]);
return this.modelSelectAll(query.sql, query.params);
}
static preview(noteId) {