1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-30 08:26:59 +02:00
joplin/ReactNativeClient/src/base-model.js

279 lines
6.7 KiB
JavaScript
Raw Normal View History

2017-05-10 21:51:43 +02:00
import { Log } from 'src/log.js';
import { Database } from 'src/database.js';
2017-05-14 23:51:45 +02:00
import { uuid } from 'src/uuid.js';
2017-06-18 01:49:52 +02:00
import { time } from 'src/time-utils.js';
2017-05-10 21:51:43 +02:00
2017-05-08 00:20:34 +02:00
class BaseModel {
2017-06-17 20:40:08 +02:00
static addModelMd(model) {
if (!model) return model;
if (Array.isArray(model)) {
let output = [];
for (let i = 0; i < model.length; i++) {
output.push(this.addModelMd(model[i]));
}
return output;
} else {
model = Object.assign({}, model);
model.type_ = this.itemType();
return model;
}
}
2017-05-10 21:51:43 +02:00
static tableName() {
throw new Error('Must be overriden');
}
2017-05-12 21:54:06 +02:00
static useUuid() {
return false;
}
2017-05-18 21:58:01 +02:00
static itemType() {
throw new Error('Must be overriden');
}
static trackChanges() {
return false;
}
2017-05-15 21:10:00 +02:00
static byId(items, id) {
for (let i = 0; i < items.length; i++) {
if (items[i].id == id) return items[i];
}
return null;
}
2017-05-19 21:32:49 +02:00
static hasField(name) {
let fields = this.fieldNames();
return fields.indexOf(name) >= 0;
}
2017-05-18 21:58:01 +02:00
static fieldNames() {
return this.db().tableFieldNames(this.tableName());
}
2017-06-15 20:18:48 +02:00
static fieldType(name) {
let fields = this.fields();
for (let i = 0; i < fields.length; i++) {
if (fields[i].name == name) return fields[i].type;
}
throw new Error('Unknown field: ' + name);
}
2017-05-20 00:16:50 +02:00
static fields() {
return this.db().tableFields(this.tableName());
}
2017-06-15 01:14:15 +02:00
static identifyItemType(item) {
2017-06-15 20:18:48 +02:00
if (!item) throw new Error('Cannot identify undefined item');
2017-06-19 21:26:27 +02:00
if ('body' in item || ('parent_id' in item && !!item.parent_id)) return BaseModel.MODEL_TYPE_NOTE;
if ('sync_time' in item) return BaseModel.MODEL_TYPE_FOLDER;
2017-06-15 01:14:15 +02:00
throw new Error('Cannot identify item: ' + JSON.stringify(item));
}
2017-05-20 00:16:50 +02:00
static new() {
let fields = this.fields();
let output = {};
for (let i = 0; i < fields.length; i++) {
let f = fields[i];
output[f.name] = f.default;
}
return output;
}
2017-05-18 21:58:01 +02:00
static fromApiResult(apiResult) {
let fieldNames = this.fieldNames();
let output = {};
for (let i = 0; i < fieldNames.length; i++) {
let f = fieldNames[i];
output[f] = f in apiResult ? apiResult[f] : null;
}
return output;
}
2017-05-18 22:31:40 +02:00
static modOptions(options) {
if (!options) {
options = {};
} else {
options = Object.assign({}, options);
}
if (!('trackChanges' in options)) options.trackChanges = true;
if (!('isNew' in options)) options.isNew = 'auto';
2017-06-18 01:49:52 +02:00
if (!('autoTimestamp' in options)) options.autoTimestamp = true;
2017-05-18 22:31:40 +02:00
return options;
}
2017-05-19 21:12:09 +02:00
static load(id) {
2017-06-11 23:11:14 +02:00
return this.loadByField('id', id);
}
2017-06-17 20:12:09 +02:00
static modelSelectOne(sql, params = null) {
if (params === null) params = [];
2017-06-17 20:40:08 +02:00
return this.db().selectOne(sql, params).then((model) => {
return this.addModelMd(model);
});
2017-06-17 20:12:09 +02:00
}
static modelSelectAll(sql, params = null) {
if (params === null) params = [];
2017-06-17 20:40:08 +02:00
return this.db().selectAll(sql, params).then((models) => {
return this.addModelMd(models);
});
2017-06-17 20:12:09 +02:00
}
2017-06-11 23:11:14 +02:00
static loadByField(fieldName, fieldValue) {
2017-06-17 20:12:09 +02:00
return this.modelSelectOne('SELECT * FROM ' + this.tableName() + ' WHERE `' + fieldName + '` = ?', [fieldValue]);
//return this.db().selectOne('SELECT * FROM ' + this.tableName() + ' WHERE `' + fieldName + '` = ?', [fieldValue]);
2017-05-19 21:12:09 +02:00
}
2017-05-19 21:32:49 +02:00
static applyPatch(model, patch) {
model = Object.assign({}, model);
for (let n in patch) {
if (!patch.hasOwnProperty(n)) continue;
model[n] = patch[n];
}
return model;
}
static diffObjects(oldModel, newModel) {
let output = {};
for (let n in newModel) {
2017-06-18 01:49:52 +02:00
if (n == 'type_') continue;
if (!newModel.hasOwnProperty(n)) continue;
if (!(n in oldModel) || newModel[n] !== oldModel[n]) {
output[n] = newModel[n];
}
}
return output;
}
2017-06-18 01:49:52 +02:00
static saveQuery(o, options) {
2017-05-20 00:16:50 +02:00
let temp = {}
let fieldNames = this.fieldNames();
for (let i = 0; i < fieldNames.length; i++) {
let n = fieldNames[i];
if (n in o) temp[n] = o[n];
}
o = temp;
2017-06-18 01:49:52 +02:00
let query = {};
2017-05-18 21:58:01 +02:00
let itemId = o.id;
2017-05-12 21:54:06 +02:00
2017-06-18 01:49:52 +02:00
if (options.autoTimestamp && this.hasField('updated_time')) {
2017-06-19 00:06:10 +02:00
o.updated_time = time.unixMs();
2017-05-19 21:32:49 +02:00
}
2017-06-18 01:49:52 +02:00
if (options.isNew) {
2017-05-19 21:12:09 +02:00
if (this.useUuid() && !o.id) {
2017-05-18 21:58:01 +02:00
itemId = uuid.create();
o.id = itemId;
}
2017-05-19 21:32:49 +02:00
if (!o.created_time && this.hasField('created_time')) {
2017-06-19 00:06:10 +02:00
o.created_time = time.unixMs();
2017-05-19 21:32:49 +02:00
}
2017-05-12 21:54:06 +02:00
query = Database.insertQuery(this.tableName(), o);
2017-05-11 22:14:01 +02:00
} else {
2017-05-12 21:54:06 +02:00
let where = { id: o.id };
let temp = Object.assign({}, o);
delete temp.id;
query = Database.updateQuery(this.tableName(), temp, where);
2017-05-11 22:14:01 +02:00
}
2017-05-12 21:54:06 +02:00
2017-05-18 21:58:01 +02:00
query.id = itemId;
2017-06-14 21:59:46 +02:00
// Log.info('Saving', JSON.stringify(o));
2017-05-20 00:16:50 +02:00
2017-05-18 21:58:01 +02:00
return query;
}
2017-05-18 22:31:40 +02:00
static save(o, options = null) {
options = this.modOptions(options);
2017-06-18 01:49:52 +02:00
options.isNew = options.isNew == 'auto' ? !o.id : options.isNew;
2017-05-18 21:58:01 +02:00
2017-06-11 23:11:14 +02:00
let queries = [];
2017-06-18 01:49:52 +02:00
let saveQuery = this.saveQuery(o, options);
2017-06-11 23:11:14 +02:00
let itemId = saveQuery.id;
2017-05-18 21:58:01 +02:00
2017-06-11 23:11:14 +02:00
queries.push(saveQuery);
2017-06-15 01:14:15 +02:00
// TODO: DISABLED DISABLED DISABLED DISABLED DISABLED DISABLED DISABLED DISABLED DISABLED DISABLED
2017-06-17 20:12:09 +02:00
// if (options.trackChanges && this.trackChanges()) {
// // Cannot import this class the normal way due to cyclical dependencies between Change and BaseModel
// // which are not handled by React Native.
// const { Change } = require('src/models/change.js');
// if (isNew) {
// let change = Change.newChange();
// change.type = Change.TYPE_CREATE;
// change.item_id = itemId;
// change.item_type = this.itemType();
// queries.push(Change.saveQuery(change));
// } else {
// for (let n in o) {
// if (!o.hasOwnProperty(n)) continue;
// if (n == 'id') continue;
// let change = Change.newChange();
// change.type = Change.TYPE_UPDATE;
// change.item_id = itemId;
// change.item_type = this.itemType();
// change.item_field = n;
// queries.push(Change.saveQuery(change));
// }
// }
// }
2017-06-11 23:11:14 +02:00
return this.db().transactionExecBatch(queries).then(() => {
2017-05-18 21:58:01 +02:00
o = Object.assign({}, o);
2017-06-11 23:11:14 +02:00
o.id = itemId;
2017-06-17 20:40:08 +02:00
o = this.addModelMd(o);
2017-05-18 21:58:01 +02:00
return o;
2017-05-21 21:55:01 +02:00
}).catch((error) => {
Log.error('Cannot save model', error);
2017-05-18 21:58:01 +02:00
});
2017-05-10 21:51:43 +02:00
}
2017-05-18 22:31:40 +02:00
static delete(id, options = null) {
options = this.modOptions(options);
2017-05-16 22:25:19 +02:00
if (!id) {
Log.warn('Cannot delete object without an ID');
return;
}
2017-05-18 22:31:40 +02:00
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id = ?', [id]).then(() => {
2017-06-17 20:12:09 +02:00
// if (options.trackChanges && this.trackChanges()) {
// const { Change } = require('src/models/change.js');
2017-05-18 22:31:40 +02:00
2017-06-17 20:12:09 +02:00
// let change = Change.newChange();
// change.type = Change.TYPE_DELETE;
// change.item_id = id;
// change.item_type = this.itemType();
2017-05-18 22:31:40 +02:00
2017-06-17 20:12:09 +02:00
// return Change.save(change);
// }
2017-05-18 22:31:40 +02:00
});
2017-05-16 22:25:19 +02:00
}
2017-05-10 21:51:43 +02:00
static db() {
2017-05-20 00:16:50 +02:00
if (!this.db_) throw new Error('Accessing database before it has been initialised');
return this.db_;
2017-05-10 21:51:43 +02:00
}
2017-05-08 00:20:34 +02:00
}
2017-06-19 21:26:27 +02:00
BaseModel.MODEL_TYPE_NOTE = 1;
BaseModel.MODEL_TYPE_FOLDER = 2;
BaseModel.MODEL_TYPE_SETTING = 3;
2017-06-06 22:01:43 +02:00
BaseModel.tableInfo_ = null;
BaseModel.tableKeys_ = null;
BaseModel.db_ = null;
2017-06-11 23:11:14 +02:00
BaseModel.dispatch = function(o) {};
2017-06-06 22:01:43 +02:00
2017-05-08 00:20:34 +02:00
export { BaseModel };