mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	got rid of flask_restful and using plain flask to handle REST API calls
This commit is contained in:
		
							
								
								
									
										27
									
								
								src/app.py
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/app.py
									
									
									
									
									
								
							@@ -6,23 +6,20 @@ from flask import Flask, request, send_from_directory
 | 
				
			|||||||
from flask import render_template, redirect
 | 
					from flask import render_template, redirect
 | 
				
			||||||
from flask_cors import CORS
 | 
					from flask_cors import CORS
 | 
				
			||||||
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user
 | 
					from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user
 | 
				
			||||||
from flask_restful import Api
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from expanded_note import ExpandedNote
 | 
					from notes_api import notes_api
 | 
				
			||||||
from move_after_note import MoveAfterNote
 | 
					 | 
				
			||||||
from move_before_note import MoveBeforeNote
 | 
					 | 
				
			||||||
from move_to_note import MoveToNote
 | 
					 | 
				
			||||||
from notes import Notes
 | 
					 | 
				
			||||||
from notes_children import NotesChildren
 | 
					 | 
				
			||||||
from notes_search import NotesSearch
 | 
					 | 
				
			||||||
from sql import connect
 | 
					from sql import connect
 | 
				
			||||||
from tree import Tree
 | 
					from tree_api import tree_api
 | 
				
			||||||
 | 
					from notes_move_api import notes_move_api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config = configparser.ConfigParser()
 | 
					config = configparser.ConfigParser()
 | 
				
			||||||
config.read('config.ini')
 | 
					config.read('config.ini')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
app.secret_key = config['Security']['flaskSecretKey']
 | 
					app.secret_key = config['Security']['flaskSecretKey']
 | 
				
			||||||
 | 
					app.register_blueprint(tree_api)
 | 
				
			||||||
 | 
					app.register_blueprint(notes_api)
 | 
				
			||||||
 | 
					app.register_blueprint(notes_move_api)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class User(UserMixin):
 | 
					class User(UserMixin):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
@@ -75,16 +72,6 @@ CORS(app)
 | 
				
			|||||||
def send_stc(path):
 | 
					def send_stc(path):
 | 
				
			||||||
    return send_from_directory(os.path.join(os.getcwd(), 'static'), path)
 | 
					    return send_from_directory(os.path.join(os.getcwd(), 'static'), path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
api = Api(app)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
api.add_resource(NotesChildren, '/notes/<string:parent_note_id>/children')
 | 
					 | 
				
			||||||
api.add_resource(MoveAfterNote, '/notes/<string:note_id>/moveAfter/<string:after_note_id>')
 | 
					 | 
				
			||||||
api.add_resource(MoveBeforeNote, '/notes/<string:note_id>/moveBefore/<string:before_note_id>')
 | 
					 | 
				
			||||||
api.add_resource(MoveToNote, '/notes/<string:note_id>/moveTo/<string:parent_id>')
 | 
					 | 
				
			||||||
api.add_resource(ExpandedNote, '/notes/<string:note_id>/expanded/<int:expanded>')
 | 
					 | 
				
			||||||
api.add_resource(Tree, '/tree')
 | 
					 | 
				
			||||||
api.add_resource(NotesSearch, '/notes')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
login_manager = LoginManager()
 | 
					login_manager = LoginManager()
 | 
				
			||||||
login_manager.init_app(app)
 | 
					login_manager.init_app(app)
 | 
				
			||||||
login_manager.login_view = 'login_form'
 | 
					login_manager.login_view = 'login_form'
 | 
				
			||||||
@@ -96,8 +83,6 @@ def load_user(user_id):
 | 
				
			|||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
api.add_resource(Notes, '/notes/<string:note_id>')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    ssl_context = None
 | 
					    ssl_context = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import execute, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ExpandedNote(Resource):
 | 
					 | 
				
			||||||
    def put(self, note_id, expanded):
 | 
					 | 
				
			||||||
        execute("update notes_tree set is_expanded = ? where note_id = ?", [expanded, note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        commit()
 | 
					 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import execute, getSingleResult, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MoveAfterNote(Resource):
 | 
					 | 
				
			||||||
    def put(self, note_id, after_note_id):
 | 
					 | 
				
			||||||
        after_note = getSingleResult("select * from notes_tree where note_id = ?", [after_note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if after_note <> None:
 | 
					 | 
				
			||||||
            execute("update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos > ?", [after_note['note_pid'], after_note['note_pos']])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [after_note['note_pid'], after_note['note_pos'] + 1, note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            commit()
 | 
					 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import execute, getSingleResult, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MoveBeforeNote(Resource):
 | 
					 | 
				
			||||||
    def put(self, note_id, before_note_id):
 | 
					 | 
				
			||||||
        before_note = getSingleResult("select * from notes_tree where note_id = ?", [before_note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if before_note <> None:
 | 
					 | 
				
			||||||
            execute("update notes_tree set note_pos = note_pos + 1 where note_id = ?", [before_note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [before_note['note_pid'], before_note['note_pos'], note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            commit()
 | 
					 | 
				
			||||||
@@ -1,19 +0,0 @@
 | 
				
			|||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import execute, getSingleResult, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MoveToNote(Resource):
 | 
					 | 
				
			||||||
    def put(self, note_id, parent_id):
 | 
					 | 
				
			||||||
        res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_id])
 | 
					 | 
				
			||||||
        max_note_pos = res['max_note_pos']
 | 
					 | 
				
			||||||
        new_note_pos = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if max_note_pos is None: # no children yet
 | 
					 | 
				
			||||||
            new_note_pos = 0
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            new_note_pos = max_note_pos + 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [parent_id, new_note_pos, note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        commit()
 | 
					 | 
				
			||||||
							
								
								
									
										70
									
								
								src/notes.py
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								src/notes.py
									
									
									
									
									
								
							@@ -1,70 +0,0 @@
 | 
				
			|||||||
import base64
 | 
					 | 
				
			||||||
import math
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from flask import request
 | 
					 | 
				
			||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import delete, execute, insert, getResults, getSingleResult, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Notes(Resource):
 | 
					 | 
				
			||||||
    def get(self, note_id):
 | 
					 | 
				
			||||||
        execute("update options set opt_value = ? where opt_name = 'start_node'", [note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if detail['note_clone_id']:
 | 
					 | 
				
			||||||
            note_id = detail['note_clone_id']
 | 
					 | 
				
			||||||
            detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            'detail': detail,
 | 
					 | 
				
			||||||
            'formatting': getResults("select * from formatting where note_id = ? order by note_offset", [note_id]),
 | 
					 | 
				
			||||||
            'links': getResults("select * from links where note_id = ? order by note_offset", [note_id]),
 | 
					 | 
				
			||||||
            'images': getResults("select * from images where note_id = ? order by note_offset", [note_id])
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def put(self, note_id):
 | 
					 | 
				
			||||||
        detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if detail['note_clone_id']:
 | 
					 | 
				
			||||||
            note_id = detail['note_clone_id']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        note = request.get_json(force=True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        now = math.floor(time.time())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        execute("update notes set note_text = ?, note_title = ?, date_modified = ? where note_id = ?", [note['detail']['note_text'], note['detail']['note_title'], now, note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        delete("formatting", note_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for fmt in note['formatting']:
 | 
					 | 
				
			||||||
            insert("formatting", fmt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        delete("images", note_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for img in note['images']:
 | 
					 | 
				
			||||||
            img['image_data'] = buffer(base64.b64decode(img['image_data']))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            insert("images", img)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        delete("links", note_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for link in note['links']:
 | 
					 | 
				
			||||||
            insert("links", link)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        commit()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def delete(self, note_id):
 | 
					 | 
				
			||||||
        children = getResults("select note_id from notes_tree where note_pid = ?", [note_id])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for child in children:
 | 
					 | 
				
			||||||
            self.delete(child['note_id'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        delete("notes_tree", note_id)
 | 
					 | 
				
			||||||
        delete("notes", note_id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        commit()
 | 
					 | 
				
			||||||
							
								
								
									
										151
									
								
								src/notes_api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/notes_api.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					import base64
 | 
				
			||||||
 | 
					import math
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
 | 
					import string
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from flask import Blueprint, jsonify
 | 
				
			||||||
 | 
					from flask import request
 | 
				
			||||||
 | 
					from flask_login import login_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sql import delete
 | 
				
			||||||
 | 
					from sql import execute, insert, commit
 | 
				
			||||||
 | 
					from sql import getResults, getSingleResult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					notes_api = Blueprint('notes_api', __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_api.route('/notes/<string:note_id>', methods = ['GET'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def getNote(note_id):
 | 
				
			||||||
 | 
					    execute("update options set opt_value = ? where opt_name = 'start_node'", [note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if detail['note_clone_id']:
 | 
				
			||||||
 | 
					        note_id = detail['note_clone_id']
 | 
				
			||||||
 | 
					        detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify({
 | 
				
			||||||
 | 
					        'detail': detail,
 | 
				
			||||||
 | 
					        'formatting': getResults("select * from formatting where note_id = ? order by note_offset", [note_id]),
 | 
				
			||||||
 | 
					        'links': getResults("select * from links where note_id = ? order by note_offset", [note_id]),
 | 
				
			||||||
 | 
					        'images': getResults("select * from images where note_id = ? order by note_offset", [note_id])
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_api.route('/notes/<string:note_id>', methods = ['PUT'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def updateNote(note_id):
 | 
				
			||||||
 | 
					    detail = getSingleResult("select * from notes where note_id = ?", [note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if detail['note_clone_id']:
 | 
				
			||||||
 | 
					        note_id = detail['note_clone_id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    note = request.get_json(force=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    now = math.floor(time.time())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    execute("update notes set note_text = ?, note_title = ?, date_modified = ? where note_id = ?", [note['detail']['note_text'], note['detail']['note_title'], now, note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete("formatting", note_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for fmt in note['formatting']:
 | 
				
			||||||
 | 
					        insert("formatting", fmt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete("images", note_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for img in note['images']:
 | 
				
			||||||
 | 
					        img['image_data'] = buffer(base64.b64decode(img['image_data']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        insert("images", img)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete("links", note_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for link in note['links']:
 | 
				
			||||||
 | 
					        insert("links", link)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_api.route('/notes/<string:note_id>', methods = ['DELETE'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def deleteNote(note_id):
 | 
				
			||||||
 | 
					    children = getResults("select note_id from notes_tree where note_pid = ?", [note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for child in children:
 | 
				
			||||||
 | 
					        delete(child['note_id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete("notes_tree", note_id)
 | 
				
			||||||
 | 
					    delete("notes", note_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit()
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_api.route('/notes/<string:parent_note_id>/children', methods = ['POST'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def createChild(parent_note_id):
 | 
				
			||||||
 | 
					    note = request.get_json(force=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    noteId = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(22))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if parent_note_id == "root":
 | 
				
			||||||
 | 
					        parent_note_id = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    new_note_pos = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if note['target'] == 'into':
 | 
				
			||||||
 | 
					        res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_note_id])
 | 
				
			||||||
 | 
					        max_note_pos = res['max_note_pos']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if max_note_pos is None: # no children yet
 | 
				
			||||||
 | 
					            new_note_pos = 0
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            new_note_pos = max_note_pos + 1
 | 
				
			||||||
 | 
					    elif note['target'] == 'after':
 | 
				
			||||||
 | 
					        after_note = getSingleResult('select note_pos from notes_tree where note_id = ?', [note['target_note_id']])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        new_note_pos = after_note['note_pos'] + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        execute('update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos > ?', [parent_note_id, after_note['note_pos']])
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise Exception('Unknown target: ' + note['target'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    now = math.floor(time.time())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    insert("notes", {
 | 
				
			||||||
 | 
					        'note_id': noteId,
 | 
				
			||||||
 | 
					        'note_title': note['note_title'],
 | 
				
			||||||
 | 
					        'note_text': '',
 | 
				
			||||||
 | 
					        'note_clone_id': '',
 | 
				
			||||||
 | 
					        'date_created': now,
 | 
				
			||||||
 | 
					        'date_modified': now,
 | 
				
			||||||
 | 
					        'icon_info': 'pencil',
 | 
				
			||||||
 | 
					        'is_finished': 0
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    insert("notes_tree", {
 | 
				
			||||||
 | 
					        'note_id': noteId,
 | 
				
			||||||
 | 
					        'note_pid': parent_note_id,
 | 
				
			||||||
 | 
					        'note_pos': new_note_pos,
 | 
				
			||||||
 | 
					        'is_expanded': 0
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify({
 | 
				
			||||||
 | 
					        'note_id': noteId
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_api.route('/notes', methods = ['GET'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def searchNotes():
 | 
				
			||||||
 | 
					    search = '%' + request.args['search'] + '%'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = getResults("select note_id from notes where note_title like ? or note_text like ?", [search, search])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    noteIdList = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for res in result:
 | 
				
			||||||
 | 
					        noteIdList.append(res['note_id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify(noteIdList)
 | 
				
			||||||
@@ -1,64 +0,0 @@
 | 
				
			|||||||
import math
 | 
					 | 
				
			||||||
import random
 | 
					 | 
				
			||||||
import string
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from flask import request
 | 
					 | 
				
			||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import execute, insert, getSingleResult, commit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NotesChildren(Resource):
 | 
					 | 
				
			||||||
    def post(self, parent_note_id):
 | 
					 | 
				
			||||||
        note = request.get_json(force=True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        noteId = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(22))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if parent_note_id == "root":
 | 
					 | 
				
			||||||
            parent_note_id = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        new_note_pos = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if note['target'] == 'into':
 | 
					 | 
				
			||||||
            res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_note_id])
 | 
					 | 
				
			||||||
            max_note_pos = res['max_note_pos']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if max_note_pos is None: # no children yet
 | 
					 | 
				
			||||||
                new_note_pos = 0
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                new_note_pos = max_note_pos + 1
 | 
					 | 
				
			||||||
        elif note['target'] == 'after':
 | 
					 | 
				
			||||||
            after_note = getSingleResult('select note_pos from notes_tree where note_id = ?', [note['target_note_id']])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            new_note_pos = after_note['note_pos'] + 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            execute('update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos > ?', [parent_note_id, after_note['note_pos']])
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise Exception('Unknown target: ' + note['target'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        now = math.floor(time.time())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        insert("notes", {
 | 
					 | 
				
			||||||
            'note_id': noteId,
 | 
					 | 
				
			||||||
            'note_title': note['note_title'],
 | 
					 | 
				
			||||||
            'note_text': '',
 | 
					 | 
				
			||||||
            'note_clone_id': '',
 | 
					 | 
				
			||||||
            'date_created': now,
 | 
					 | 
				
			||||||
            'date_modified': now,
 | 
					 | 
				
			||||||
            'icon_info': 'pencil',
 | 
					 | 
				
			||||||
            'is_finished': 0
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        insert("notes_tree", {
 | 
					 | 
				
			||||||
            'note_id': noteId,
 | 
					 | 
				
			||||||
            'note_pid': parent_note_id,
 | 
					 | 
				
			||||||
            'note_pos': new_note_pos,
 | 
					 | 
				
			||||||
            'is_expanded': 0
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        commit()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            'note_id': noteId
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
							
								
								
									
										57
									
								
								src/notes_move_api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/notes_move_api.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					from flask import Blueprint, jsonify
 | 
				
			||||||
 | 
					from flask_login import login_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sql import execute, commit
 | 
				
			||||||
 | 
					from sql import getSingleResult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					notes_move_api = Blueprint('notes_move_api', __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_move_api.route('/notes/<string:note_id>/moveTo/<string:parent_id>', methods = ['PUT'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def moveToNote(note_id, parent_id):
 | 
				
			||||||
 | 
					    res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_id])
 | 
				
			||||||
 | 
					    max_note_pos = res['max_note_pos']
 | 
				
			||||||
 | 
					    new_note_pos = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if max_note_pos is None:  # no children yet
 | 
				
			||||||
 | 
					        new_note_pos = 0
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        new_note_pos = max_note_pos + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [parent_id, new_note_pos, note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit()
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_move_api.route('/notes/<string:note_id>/moveBefore/<string:before_note_id>', methods = ['PUT'])
 | 
				
			||||||
 | 
					def moveBeforeNote(note_id, before_note_id):
 | 
				
			||||||
 | 
					    before_note = getSingleResult("select * from notes_tree where note_id = ?", [before_note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if before_note <> None:
 | 
				
			||||||
 | 
					        execute("update notes_tree set note_pos = note_pos + 1 where note_id = ?", [before_note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [before_note['note_pid'], before_note['note_pos'], note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_move_api.route('/notes/<string:note_id>/moveAfter/<string:after_note_id>', methods = ['PUT'])
 | 
				
			||||||
 | 
					def moveAfterNote(note_id, after_note_id):
 | 
				
			||||||
 | 
					    after_note = getSingleResult("select * from notes_tree where note_id = ?", [after_note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if after_note <> None:
 | 
				
			||||||
 | 
					        execute("update notes_tree set note_pos = note_pos + 1 where note_pid = ? and note_pos > ?", [after_note['note_pid'], after_note['note_pos']])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [after_note['note_pid'], after_note['note_pos'] + 1, note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@notes_move_api.route('/notes/<string:note_id>/expanded/<int:expanded>', methods = ['PUT'])
 | 
				
			||||||
 | 
					def setExpandedNote(note_id, expanded):
 | 
				
			||||||
 | 
					    execute("update notes_tree set is_expanded = ? where note_id = ?", [expanded, note_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit()
 | 
				
			||||||
 | 
					    return jsonify({})
 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
from flask import request
 | 
					 | 
				
			||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import getResults
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NotesSearch(Resource):
 | 
					 | 
				
			||||||
    def get(self):
 | 
					 | 
				
			||||||
        search = '%' + request.args['search'] + '%'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        result = getResults("select note_id from notes where note_title like ? or note_text like ?", [search, search])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        noteIdList = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for res in result:
 | 
					 | 
				
			||||||
            noteIdList.append(res['note_id'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return noteIdList
 | 
					 | 
				
			||||||
							
								
								
									
										40
									
								
								src/tree.py
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								src/tree.py
									
									
									
									
									
								
							@@ -1,40 +0,0 @@
 | 
				
			|||||||
from flask_restful import Resource
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from sql import getResults, getSingleResult
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Tree(Resource):
 | 
					 | 
				
			||||||
    def get(self):
 | 
					 | 
				
			||||||
        notes = getResults("select "
 | 
					 | 
				
			||||||
                           "notes_tree.*, "
 | 
					 | 
				
			||||||
                           "COALESCE(clone.note_title, notes.note_title) as note_title, "
 | 
					 | 
				
			||||||
                           "notes.note_clone_id, "        
 | 
					 | 
				
			||||||
                           "case when notes.note_clone_id is null or notes.note_clone_id = '' then 0 else 1 end as is_clone "
 | 
					 | 
				
			||||||
                           "from notes_tree "
 | 
					 | 
				
			||||||
                           "join notes on notes.note_id = notes_tree.note_id "
 | 
					 | 
				
			||||||
                           "left join notes as clone on notes.note_clone_id = clone.note_id "
 | 
					 | 
				
			||||||
                           "order by note_pid, note_pos")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rootNotes = []
 | 
					 | 
				
			||||||
        notesMap = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for note in notes:
 | 
					 | 
				
			||||||
            note['children'] = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if not note['note_pid']:
 | 
					 | 
				
			||||||
                rootNotes.append(note)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            notesMap[note['note_id']] = note
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for note in notes:
 | 
					 | 
				
			||||||
            if note['note_pid'] != "":
 | 
					 | 
				
			||||||
                parent = notesMap[note['note_pid']]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                parent['children'].append(note)
 | 
					 | 
				
			||||||
                parent['folder'] = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        retObject = {}
 | 
					 | 
				
			||||||
        retObject['notes'] = rootNotes
 | 
					 | 
				
			||||||
        retObject['start_note_id'] = getSingleResult('select * from options where opt_name = "start_node"')['opt_value'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return retObject
 | 
					 | 
				
			||||||
							
								
								
									
										43
									
								
								src/tree_api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/tree_api.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					from flask import Blueprint, jsonify
 | 
				
			||||||
 | 
					from flask_login import login_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sql import getResults, getSingleResult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tree_api = Blueprint('tree_api', __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@tree_api.route('/tree', methods = ['GET'])
 | 
				
			||||||
 | 
					@login_required
 | 
				
			||||||
 | 
					def getTree():
 | 
				
			||||||
 | 
					    notes = getResults("select "
 | 
				
			||||||
 | 
					                       "notes_tree.*, "
 | 
				
			||||||
 | 
					                       "COALESCE(clone.note_title, notes.note_title) as note_title, "
 | 
				
			||||||
 | 
					                       "notes.note_clone_id, "        
 | 
				
			||||||
 | 
					                       "case when notes.note_clone_id is null or notes.note_clone_id = '' then 0 else 1 end as is_clone "
 | 
				
			||||||
 | 
					                       "from notes_tree "
 | 
				
			||||||
 | 
					                       "join notes on notes.note_id = notes_tree.note_id "
 | 
				
			||||||
 | 
					                       "left join notes as clone on notes.note_clone_id = clone.note_id "
 | 
				
			||||||
 | 
					                       "order by note_pid, note_pos")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rootNotes = []
 | 
				
			||||||
 | 
					    notesMap = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for note in notes:
 | 
				
			||||||
 | 
					        note['children'] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not note['note_pid']:
 | 
				
			||||||
 | 
					            rootNotes.append(note)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        notesMap[note['note_id']] = note
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for note in notes:
 | 
				
			||||||
 | 
					        if note['note_pid'] != "":
 | 
				
			||||||
 | 
					            parent = notesMap[note['note_pid']]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            parent['children'].append(note)
 | 
				
			||||||
 | 
					            parent['folder'] = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    retObject = {}
 | 
				
			||||||
 | 
					    retObject['notes'] = rootNotes
 | 
				
			||||||
 | 
					    retObject['start_note_id'] = getSingleResult('select * from options where opt_name = "start_node"')['opt_value'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return jsonify(retObject)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user