mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Loading and saving note to SQLite
This commit is contained in:
parent
017c4f7338
commit
3d46cf4b55
@ -9,7 +9,8 @@
|
||||
"dependencies": {
|
||||
"react": "16.0.0-alpha.6",
|
||||
"react-native": "0.44.0",
|
||||
"react-navigation": "^1.0.0-beta.9"
|
||||
"react-navigation": "^1.0.0-beta.9",
|
||||
"uuid": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-jest": "19.0.0",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Log } from 'src/log.js';
|
||||
import { Database } from 'src/database.js';
|
||||
import createUuid from 'uuid/v4';
|
||||
|
||||
class BaseModel {
|
||||
|
||||
@ -7,9 +8,16 @@ class BaseModel {
|
||||
throw new Error('Must be overriden');
|
||||
}
|
||||
|
||||
static save(object) {
|
||||
let sql = Database.insertSql(this.tableName(), object);
|
||||
Log.info(sql);
|
||||
static save(o) {
|
||||
let isNew = !o.id;
|
||||
if (isNew) o.id = createUuid();
|
||||
if (isNew) {
|
||||
let q = Database.insertQuery(this.tableName(), o);
|
||||
return this.db().insert(q.sql, q.params);
|
||||
} else {
|
||||
Log.error('NOT EIMPLEMETNED');
|
||||
// TODO: update
|
||||
}
|
||||
}
|
||||
|
||||
static setDb(database) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux'
|
||||
import { ListView, Text, TouchableHighlight } from 'react-native';
|
||||
import { Log } from 'src/log.js';
|
||||
import { _ } from 'src/locale.js';
|
||||
|
||||
class ItemListComponent extends Component {
|
||||
@ -17,11 +18,12 @@ class ItemListComponent extends Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
// TODO: use this to update:
|
||||
// https://stackoverflow.com/questions/38186114/react-native-redux-and-listview
|
||||
this.setState({ dataSource: this.state.dataSource.cloneWithRows(newProps.notes) });
|
||||
}
|
||||
|
||||
render() {
|
||||
Log.info('RENDER');
|
||||
let renderRow = (rowData) => {
|
||||
let onPress = () => {
|
||||
this.props.onItemClick(rowData.id)
|
||||
|
@ -82,14 +82,21 @@ INSERT INTO version (version) VALUES (1);
|
||||
|
||||
class Database {
|
||||
|
||||
constructor() {}
|
||||
constructor() {
|
||||
this.debugMode_ = false;
|
||||
}
|
||||
|
||||
setDebugEnabled(v) {
|
||||
SQLite.DEBUG(v);
|
||||
this.debugMode_ = v;
|
||||
}
|
||||
|
||||
debugMode() {
|
||||
return this.debugMode_;
|
||||
}
|
||||
|
||||
open() {
|
||||
this.db_ = SQLite.openDatabase({ name: 'joplin.sqlite', location: 'Documents' }, (db) => {
|
||||
this.db_ = SQLite.openDatabase({ name: '/storage/emulated/0/Download/joplin.sqlite' }, (db) => {
|
||||
Log.info('Database was open successfully');
|
||||
}, (error) => {
|
||||
Log.error('Cannot open database: ', error);
|
||||
@ -115,7 +122,14 @@ class Database {
|
||||
return output;
|
||||
}
|
||||
|
||||
logQuery(sql, params = null) {
|
||||
if (!this.debugMode()) return;
|
||||
Log.debug('DB: ' + sql, params);
|
||||
}
|
||||
|
||||
selectOne(sql, params = null) {
|
||||
this.logQuery(sql, params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db_.executeSql(sql, params, (r) => {
|
||||
resolve(r.rows.length ? r.rows.item(0) : null);
|
||||
@ -125,24 +139,65 @@ class Database {
|
||||
});
|
||||
}
|
||||
|
||||
static insertSql(tableName, data) {
|
||||
let output = '';
|
||||
selectAll(sql, params = null) {
|
||||
this.logQuery(sql, params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db_.executeSql(sql, params, (r) => {
|
||||
resolve(r);
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
insert(sql, params = null) {
|
||||
this.logQuery(sql, params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db_.executeSql(sql, params, (r) => {
|
||||
resolve();
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
del(sql, params = null) {
|
||||
this.logQuery(sql, params);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db_.executeSql(sql, params, (r) => {
|
||||
resolve();
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static insertQuery(tableName, data) {
|
||||
let keySql= '';
|
||||
let valueSql = '';
|
||||
let params = [];
|
||||
for (let key in data) {
|
||||
if (data.hasOwnProperty(key)) continue;
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (keySql != '') keySql += ', ';
|
||||
if (valueSql != '') valueSql += ', ';
|
||||
keySql += key;
|
||||
keySql += '`' + key + '`';
|
||||
valueSql += '?';
|
||||
params.push(data[key]);
|
||||
}
|
||||
return 'INSERT INTO ' + tableName + ' (' + keySql + ') VALUES (' + valueSql + ')';
|
||||
return {
|
||||
sql: 'INSERT INTO `' + tableName + '` (' + keySql + ') VALUES (' + valueSql + ')',
|
||||
params: params,
|
||||
};
|
||||
}
|
||||
|
||||
updateSchema() {
|
||||
Log.info('Checking for database schema update...');
|
||||
|
||||
this.selectOne('SELECT * FROM version LIMIT 1').then((row) => {
|
||||
Log.info('Current database version', row);
|
||||
// TODO: version update logic
|
||||
}).catch((error) => {
|
||||
// Assume that error was:
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
class Log {
|
||||
|
||||
static debug(...o) {
|
||||
console.debug(...o);
|
||||
}
|
||||
|
||||
static info(...o) {
|
||||
console.info(...o);
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ import { BaseModel } from 'src/base-model.js';
|
||||
function main() {
|
||||
let debugMode = true;
|
||||
let clientId = 'A7D301DA7D301DA7D301DA7D301DA7D3';
|
||||
|
||||
|
||||
AppRegistry.registerComponent('AwesomeProject', () => Root);
|
||||
|
||||
let db = new Database();
|
||||
db.setDebugEnabled(debugMode);
|
||||
db.open();
|
||||
|
||||
BaseModel.setDb(db);
|
||||
|
||||
AppRegistry.registerComponent('AwesomeProject', () => Root);
|
||||
BaseModel.setDb(db);
|
||||
}
|
||||
|
||||
export { main }
|
@ -1,4 +1,5 @@
|
||||
import { BaseModel } from 'src/base-model.js';
|
||||
import { Log } from 'src/log.js';
|
||||
|
||||
class Note extends BaseModel {
|
||||
|
||||
@ -21,6 +22,16 @@ class Note extends BaseModel {
|
||||
}
|
||||
}
|
||||
|
||||
static previews() {
|
||||
return this.db().selectAll('SELECT id, title, body, updated_time FROM notes').then((r) => {
|
||||
let output = [];
|
||||
for (let i = 0; i < r.rows.length; i++) {
|
||||
output.push(r.rows.item(i));
|
||||
}
|
||||
return output;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Note };
|
@ -24,8 +24,6 @@ let defaultState = {
|
||||
const reducer = (state = defaultState, action) => {
|
||||
Log.info('Reducer action', action);
|
||||
|
||||
Log.info('DB LA', Note.db());
|
||||
|
||||
let newState = state;
|
||||
|
||||
switch (action.type) {
|
||||
@ -45,11 +43,16 @@ const reducer = (state = defaultState, action) => {
|
||||
|
||||
break;
|
||||
|
||||
case 'VIEW_NOTE':
|
||||
case 'NOTES_LOADED':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.notes = action.notes;
|
||||
break;
|
||||
|
||||
break;
|
||||
case 'SAVE_NOTE':
|
||||
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -102,7 +105,7 @@ class NoteScreenComponent extends React.Component {
|
||||
this.setState({ note: this.props.note });
|
||||
}
|
||||
|
||||
noteComponent_onChange = (propName, propValue) => {
|
||||
noteComponent_change = (propName, propValue) => {
|
||||
this.setState((prevState, props) => {
|
||||
let note = Object.assign({}, prevState.note);
|
||||
note[propName] = propValue;
|
||||
@ -110,25 +113,39 @@ class NoteScreenComponent extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
title_onChangeText = (text) => {
|
||||
this.noteComponent_onChange('title', text);
|
||||
title_changeText = (text) => {
|
||||
this.noteComponent_change('title', text);
|
||||
}
|
||||
|
||||
body_onChangeText = (text) => {
|
||||
this.noteComponent_onChange('body', text);
|
||||
body_changeText = (text) => {
|
||||
this.noteComponent_change('body', text);
|
||||
}
|
||||
|
||||
saveNoteButton_press = () => {
|
||||
// TODO: if state changes are asynchronous, how to be sure that, when
|
||||
// the button is presssed, this.state.note contains the actual note?
|
||||
// - Save to database
|
||||
// - Dispatch "noteSaved" when done
|
||||
// -* Move i^p on state
|
||||
|
||||
Note.save(this.state.note).then(() => {
|
||||
Log.info('NOTE INSERTED');
|
||||
}).catch((error) => {
|
||||
Log.warn('CANONT INSERT NOTE', error);
|
||||
});
|
||||
|
||||
// this.props.dispatch({
|
||||
// type: 'SAVE_NOTE',
|
||||
// note: this.state.note,
|
||||
// });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
let onSaveButtonPress = () => {
|
||||
return this.props.onSaveButtonPress(this.state.note);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<TextInput value={this.state.note.title} onChangeText={this.title_onChangeText} />
|
||||
<TextInput style={{flex: 1, textAlignVertical: 'top'}} multiline={true} value={this.state.note.body} onChangeText={this.body_onChangeText} />
|
||||
<Button title="Save note" onPress={onSaveButtonPress} />
|
||||
<TextInput value={this.state.note.title} onChangeText={this.title_changeText} />
|
||||
<TextInput style={{flex: 1, textAlignVertical: 'top'}} multiline={true} value={this.state.note.body} onChangeText={this.body_changeText} />
|
||||
<Button title="Save note" onPress={this.saveNoteButton_press} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -139,13 +156,7 @@ const NoteScreen = connect(
|
||||
(state) => {
|
||||
return {
|
||||
note: state.selectedNoteId ? Note.noteById(state.notes, state.selectedNoteId) : Note.newNote(),
|
||||
onSaveButtonPress: (note) => {
|
||||
Log.info(note);
|
||||
}
|
||||
};
|
||||
},
|
||||
(dispatch) => {
|
||||
return {};
|
||||
}
|
||||
)(NoteScreenComponent)
|
||||
|
||||
@ -155,14 +166,26 @@ const AppNavigator = StackNavigator({
|
||||
});
|
||||
|
||||
class AppComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<AppNavigator navigation={addNavigationHelpers({
|
||||
dispatch: this.props.dispatch,
|
||||
state: this.props.nav,
|
||||
})} />
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Note.previews().then((notes) => {
|
||||
this.props.dispatch({
|
||||
type: 'NOTES_LOADED',
|
||||
notes: notes,
|
||||
});
|
||||
}).catch((error) => {
|
||||
Log.warn('Cannot load notes', error);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<AppNavigator navigation={addNavigationHelpers({
|
||||
dispatch: this.props.dispatch,
|
||||
state: this.props.nav,
|
||||
})} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
defaultState.nav = AppNavigator.router.getStateForAction(AppNavigator.router.getActionForPathAndParams('Notes'));
|
||||
|
Loading…
Reference in New Issue
Block a user