1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-23 18:53:36 +02:00

Removed default folder concept

This commit is contained in:
Laurent Cozic 2017-06-25 08:52:25 +01:00
parent e1de43988d
commit 79e0bb2e65
7 changed files with 54 additions and 90 deletions

View File

@ -63,12 +63,12 @@ async function main() {
// console.info('DELETING ALL DATA');
// await db.exec('DELETE FROM notes');
// await db.exec('DELETE FROM changes');
// await db.exec('DELETE FROM folders WHERE is_default != 1');
// await db.exec('DELETE FROM folders');
// await db.exec('DELETE FROM resources');
// await db.exec('DELETE FROM deleted_items');
// await db.exec('DELETE FROM tags');
// await db.exec('DELETE FROM note_tags');
// let folder1 = await Folder.save({ title: 'test1', is_default: 1 });
// let folder1 = await Folder.save({ title: 'test1' });
// let folder2 = await Folder.save({ title: 'test2' });
// await importEnex(folder1.id, '/mnt/c/Users/Laurent/Desktop/Laurent.enex');
// return;
@ -324,13 +324,27 @@ async function main() {
commands.push({
usage: 'rm <item-title>',
description: 'Deletes the given item. For a notebook, all the notes within that notebook will be deleted.',
description: 'Deletes the given item. For a notebook, all the notes within that notebook will be deleted. Use `rm ../<notebook-name>` to delete a notebook.',
action: async function(args, end) {
let title = args['item-title'];
let itemType = currentFolder ? BaseModel.MODEL_TYPE_NOTE : BaseModel.MODEL_TYPE_FOLDER;
let itemType = null;
if (title.substr(0, 3) == '../') {
itemType = BaseModel.MODEL_TYPE_FOLDER;
title = title.substr(3);
} else {
itemType = BaseModel.MODEL_TYPE_NOTE;
}
let item = await BaseItem.loadItemByField(itemType, 'title', title);
if (!item) return commandError(this, _('No item with title "%s" found.', title), end);
await BaseItem.deleteItem(itemType, item.id);
if (currentFolder && currentFolder.id == item.id) {
let f = await Folder.defaultFolder();
switchCurrentFolder(f);
}
end();
},
autocomplete: autocompleteItems,

View File

@ -9,44 +9,4 @@ import { BaseModel } from 'lib/base-model.js';
process.on('unhandledRejection', (reason, p) => {
console.error('Unhandled promise rejection at: Promise', p, 'reason:', reason);
});
async function thereIsOnlyOneDefaultFolder() {
let count = 0;
let folders = await Folder.all();
for (let i = 0; i < folders.length; i++) {
if (!!folders[i].is_default) count++;
}
return count === 1;
}
describe('Folder', function() {
beforeEach( async (done) => {
await setupDatabase(1);
switchClient(1);
done();
});
it('should have one default folder only', async (done) => {
let f1 = await Folder.save({ title: 'folder1', is_default: 1 });
let f2 = await Folder.save({ title: 'folder2' });
let f3 = await Folder.save({ title: 'folder3' });
await Folder.save({ id: f2.id, is_default: 1 });
f2 = await Folder.load(f2.id);
expect(f2.is_default).toBe(1);
let r = await thereIsOnlyOneDefaultFolder();
expect(r).toBe(true);
await Folder.save({ id: f2.id, is_default: 0 });
f2 = await Folder.load(f2.id);
expect(f2.is_default).toBe(1);
done();
});
});

View File

@ -53,7 +53,7 @@ class SideMenuContentComponent extends Component {
let buttons = [];
for (let i = 0; i < this.props.folders.length; i++) {
let f = this.props.folders[i];
let title = f.title + (f.is_default ? ' *' : '');
let title = f.title;
buttons.push(
<Button style={styles.button} title={title} onPress={() => { this.folder_press(f) }} key={f.id} />
);

View File

@ -254,10 +254,7 @@ class BaseModel {
static delete(id, options = null) {
options = this.modOptions(options);
if (!id) {
Log.warn('Cannot delete object without an ID');
return;
}
if (!id) throw new Error('Cannot delete object without an ID');
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id = ?', [id]).then(() => {
let trackDeleted = this.trackDeleted();

View File

@ -10,8 +10,7 @@ CREATE TABLE folders (
title TEXT NOT NULL DEFAULT "",
created_time INT NOT NULL DEFAULT 0,
updated_time INT NOT NULL DEFAULT 0,
sync_time INT NOT NULL DEFAULT 0,
is_default INT NOT NULL DEFAULT 0
sync_time INT NOT NULL DEFAULT 0
);
CREATE TABLE notes (
@ -437,7 +436,7 @@ class Database {
let queries = this.wrapQueries(this.sqlStringToLines(structureSql));
queries.push(this.wrapQuery('INSERT INTO settings (`key`, `value`, `type`) VALUES ("clientId", "' + uuid.create() + '", "' + Database.enumId('settings', 'string') + '")'));
queries.push(this.wrapQuery('INSERT INTO folders (`id`, `title`, `is_default`, `created_time`) VALUES ("' + uuid.create() + '", "' + _('Notebook') + '", 1, ' + (new Date()).getTime() + ')'));
queries.push(this.wrapQuery('INSERT INTO folders (`id`, `title`, `created_time`) VALUES ("' + uuid.create() + '", "' + _('Notebook') + '", ' + (new Date()).getTime() + ')'));
return this.transactionExecBatch(queries).then(() => {
this.logger().info('Database schema created successfully');

View File

@ -43,6 +43,21 @@ class BaseItem extends BaseModel {
});
}
static loadItemByField(itemType, field, value) {
let ItemClass = this.itemClass(itemType);
return ItemClass.loadByField(field, value);
}
static loadItem(itemType, id) {
let ItemClass = this.itemClass(itemType);
return ItemClass.load(id);
}
static deleteItem(itemType, id) {
let ItemClass = this.itemClass(itemType);
return ItemClass.delete(id);
}
static serialize_format(propName, propValue) {
if (['created_time', 'updated_time'].indexOf(propName) >= 0) {
if (!propValue) return '';

View File

@ -57,31 +57,23 @@ class Folder extends BaseItem {
});
}
static delete(folderId, options = null) {
return this.load(folderId).then((folder) => {
if (!folder) throw new Error('Trying to delete non-existing folder: ' + folderId);
static async delete(folderId, options = null) {
let folder = await Folder.load(folderId);
if (!folder) throw new Error('Trying to delete non-existing notebook: ' + folderId);
if (!!folder.is_default) {
throw new Error(_('Cannot delete the default list'));
}
}).then(() => {
return this.noteIds(folderId);
}).then((ids) => {
let chain = [];
for (let i = 0; i < ids.length; i++) {
chain.push(() => {
return Note.delete(ids[i]);
});
}
let count = await Folder.count();
if (count <= 1) throw new Error(_('Cannot delete the last notebook'));
return promiseChain(chain);
}).then(() => {
return super.delete(folderId, options);
}).then(() => {
this.dispatch({
type: 'FOLDER_DELETE',
folderId: folderId,
});
let noteIds = await Folder.noteIds(folderId);
for (let i = 0; i < noteIds.length; i++) {
await Note.delete(noteIds[i]);
}
super.delete(folderId, options);
this.dispatch({
type: 'FOLDER_DELETE',
folderId: folderId,
});
}
@ -98,25 +90,12 @@ class Folder extends BaseItem {
}
static async defaultFolder() {
return this.modelSelectOne('SELECT * FROM folders WHERE is_default = 1');
return this.modelSelectOne('SELECT * FROM folders ORDER BY created_time DESC LIMIT 1');
}
static save(o, options = null) {
return Folder.loadByField('title', o.title).then((existingFolder) => {
if (existingFolder && existingFolder.id != o.id) throw new Error(_('A folder with title "%s" already exists', o.title));
if ('is_default' in o) {
if (!o.is_default) {
o = Object.assign({}, o);
delete o.is_default;
Log.warn('is_default property cannot be set to 0 directly. Instead, set the folder that should become the default to 1.');
} else {
options = this.modOptions(options);
options.transactionNextQueries.push(
{ sql: 'UPDATE folders SET is_default = 0 WHERE id != ?', params: [o.id] },
);
}
}
if (existingFolder && existingFolder.id != o.id) throw new Error(_('A notebook with title "%s" already exists', o.title));
return super.save(o, options).then((folder) => {
this.dispatch({