diff --git a/.ipynb_checkpoints/setup-checkpoint.py b/.ipynb_checkpoints/setup-checkpoint.py new file mode 100644 index 0000000..7467f60 --- /dev/null +++ b/.ipynb_checkpoints/setup-checkpoint.py @@ -0,0 +1,13 @@ +from setuptools import find_packages, setup + +setup( + name='exquisite_branch', + version='1.0.0', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=[ + 'flask', + 'shortuuid' + ], +) diff --git a/exquisite_branch/.ipynb_checkpoints/__init__-checkpoint.py b/exquisite_branch/.ipynb_checkpoints/__init__-checkpoint.py new file mode 100644 index 0000000..1be4731 --- /dev/null +++ b/exquisite_branch/.ipynb_checkpoints/__init__-checkpoint.py @@ -0,0 +1,61 @@ +import os +from flask import Flask + +class PrefixMiddleware(object): + + def __init__(self, app, prefix=''): + self.app = app + self.prefix = prefix + + def __call__(self, environ, start_response): + + if environ['PATH_INFO'].startswith(self.prefix): + environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):] + environ['SCRIPT_NAME'] = self.prefix + return self.app(environ, start_response) + else: + start_response('404', [('Content-Type', 'text/plain')]) + return ["This url does not belong to the app.".encode()] + + +def create_app(test_config=None): + # create and configure the app + app = Flask(__name__, instance_relative_config=True) + app.config.from_mapping( + SECRET_KEY='dev', + DATABASE=os.path.join(app.instance_path, 'exquisite'), + ) + + + if test_config is None: + # load the instance config, if it exists, when not testing + app.config.from_pyfile('config.py', silent=True) + else: + # load the test config if passed in + app.config.from_mapping(test_config) + + # ensure the instance folder exists + try: + os.makedirs(app.instance_path) + except OSError: + pass + + from . import db + db.init_app(app) + + from . import draw + app.register_blueprint(draw.bp) + + from . import share + app.register_blueprint(share.bp) + + from . import display + app.register_blueprint(display.bp) + + from . import home + app.register_blueprint(home.bp) + + + app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/soupboat/xquisite') + + return app diff --git a/exquisite_branch/.ipynb_checkpoints/draw-checkpoint.py b/exquisite_branch/.ipynb_checkpoints/draw-checkpoint.py new file mode 100644 index 0000000..2793c6e --- /dev/null +++ b/exquisite_branch/.ipynb_checkpoints/draw-checkpoint.py @@ -0,0 +1,90 @@ +from flask import (Blueprint, flash, g, redirect, + render_template, request, session, url_for) + +from exquisite_branch.db import get_db +from werkzeug.exceptions import abort + +from shortuuid import uuid + +bp = Blueprint('draw', __name__, url_prefix='/draw') + + +@bp.route('/', methods=('GET', 'POST')) +def draw(parent=None): + db = get_db() + + if request.method == 'POST': + content = request.form.get('content') + branch = request.form.get('branch') + if request.is_json: + data = request.get_json() + content = data['content'] + branch = data['branch'] + + + db.execute( + 'INSERT INTO branches (content, parent, branch) VALUES (?, ?, ?)', + (content, parent, branch,) + ) + db.commit() + print(url_for('share.share', branch=f"{branch}")) + return redirect(url_for('share.share', branch=branch)) + + branch = uuid() + + previous = db.execute( + "SELECT content, branch, parent FROM branches" + " WHERE branch = ?", + (parent,) + ).fetchone() + + if previous is None: + abort(404, f"Previous with id {parent} doesn't exist") + + return render_template('draw.html', parent=parent, content=previous['content'], branch=branch) + + +@bp.route('/last', methods=('GET', 'POST')) +def last(): + + branch = uuid() + db = get_db() + previous = db.execute( + 'SELECT * FROM branches ORDER BY id DESC LIMIT 1' + ).fetchone() + + parent = previous['branch'] + + if request.method == 'POST': + content = request.form['content'] + branch = request.form['branch'] + + db.execute( + 'INSERT INTO branches (content, parent, branch) VALUES (?, ?, ?)', + (content, parent, branch,) + ) + db.commit() + print(url_for('share.share', branch=f"{branch}")) + return redirect(url_for('share.share', branch=branch)) + + return render_template('draw.html', parent=parent, content=previous['content'], branch=branch) + + +@bp.route('/', methods=('GET', 'POST')) +def new(): + db = get_db() + branch = uuid() + parent = 'NEW' + + if request.method == 'POST': + content = request.form['content'] + branch = request.form['branch'] + + db.execute( + 'INSERT INTO branches (content, parent, branch) VALUES (?, ?, ?)', + (content, parent, branch,) + ) + db.commit() + return redirect(url_for('share.share', branch=branch)) + + return render_template('draw.html', parent=parent, branch=branch) diff --git a/exquisite_branch/.ipynb_checkpoints/home-checkpoint.py b/exquisite_branch/.ipynb_checkpoints/home-checkpoint.py new file mode 100644 index 0000000..a968c1f --- /dev/null +++ b/exquisite_branch/.ipynb_checkpoints/home-checkpoint.py @@ -0,0 +1,7 @@ +from flask import (Blueprint, render_template) +bp = Blueprint('home', __name__, url_prefix='/') + + +@bp.route('/') +def home(): + return render_template('home.html') diff --git a/exquisite_branch/.ipynb_checkpoints/share-checkpoint.py b/exquisite_branch/.ipynb_checkpoints/share-checkpoint.py new file mode 100644 index 0000000..d77b598 --- /dev/null +++ b/exquisite_branch/.ipynb_checkpoints/share-checkpoint.py @@ -0,0 +1,9 @@ +from flask import (Blueprint, flash, g, redirect, + render_template, request, session, url_for) + + +bp = Blueprint('share', __name__, url_prefix='/share') + +@bp.route('//') +def share(branch=None): + return render_template('share.html', branch=branch) diff --git a/exquisite_branch/__init__.py b/exquisite_branch/__init__.py index 8d38243..1be4731 100644 --- a/exquisite_branch/__init__.py +++ b/exquisite_branch/__init__.py @@ -1,6 +1,22 @@ import os from flask import Flask +class PrefixMiddleware(object): + + def __init__(self, app, prefix=''): + self.app = app + self.prefix = prefix + + def __call__(self, environ, start_response): + + if environ['PATH_INFO'].startswith(self.prefix): + environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):] + environ['SCRIPT_NAME'] = self.prefix + return self.app(environ, start_response) + else: + start_response('404', [('Content-Type', 'text/plain')]) + return ["This url does not belong to the app.".encode()] + def create_app(test_config=None): # create and configure the app @@ -9,6 +25,7 @@ def create_app(test_config=None): SECRET_KEY='dev', DATABASE=os.path.join(app.instance_path, 'exquisite'), ) + if test_config is None: # load the instance config, if it exists, when not testing @@ -16,7 +33,7 @@ def create_app(test_config=None): else: # load the test config if passed in app.config.from_mapping(test_config) - + # ensure the instance folder exists try: os.makedirs(app.instance_path) @@ -38,4 +55,7 @@ def create_app(test_config=None): from . import home app.register_blueprint(home.bp) + + app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/soupboat/xquisite') + return app diff --git a/exquisite_branch/draw.py b/exquisite_branch/draw.py index f2696b7..2793c6e 100644 --- a/exquisite_branch/draw.py +++ b/exquisite_branch/draw.py @@ -27,6 +27,7 @@ def draw(parent=None): (content, parent, branch,) ) db.commit() + print(url_for('share.share', branch=f"{branch}")) return redirect(url_for('share.share', branch=branch)) branch = uuid() @@ -63,6 +64,7 @@ def last(): (content, parent, branch,) ) db.commit() + print(url_for('share.share', branch=f"{branch}")) return redirect(url_for('share.share', branch=branch)) return render_template('draw.html', parent=parent, content=previous['content'], branch=branch) diff --git a/exquisite_branch/share.py b/exquisite_branch/share.py index f0a24b0..d77b598 100644 --- a/exquisite_branch/share.py +++ b/exquisite_branch/share.py @@ -4,7 +4,6 @@ from flask import (Blueprint, flash, g, redirect, bp = Blueprint('share', __name__, url_prefix='/share') - -@bp.route('/') +@bp.route('//') def share(branch=None): return render_template('share.html', branch=branch) diff --git a/exquisite_branch/static/js/.ipynb_checkpoints/draw-checkpoint.js b/exquisite_branch/static/js/.ipynb_checkpoints/draw-checkpoint.js new file mode 100644 index 0000000..8935639 --- /dev/null +++ b/exquisite_branch/static/js/.ipynb_checkpoints/draw-checkpoint.js @@ -0,0 +1,114 @@ +// Great resource from https://stackoverflow.com/a/40700068 +// Thank you ConnorFan + +var strokeWidth = 2; +var bufferSize; + +var svgElement = document.getElementById("svgElement"); +var rect = svgElement.getBoundingClientRect(); +var path = null; +var strPath; +var buffer = []; // Contains the last positions of the mouse cursor + +svgElement.addEventListener("mousedown", function (e) { + bufferSize = document.getElementById("cmbBufferSize").value; + path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + path.setAttribute("stroke", "currentColor"); + path.setAttribute("stroke-width", strokeWidth); + buffer = []; + var pt = getMousePosition(e); + appendToBuffer(pt); + strPath = "M" + pt.x + " " + pt.y; + path.setAttribute("d", strPath); + svgElement.appendChild(path); +}); + +svgElement.addEventListener("mousemove", function (e) { + if (path) { + appendToBuffer(getMousePosition(e)); + updateSvgPath(); + } +}); + +svgElement.addEventListener("mouseup", function () { + if (path) { + path = null; + } +}); + +svgElement.addEventListener("mouseleave", function () { + if (path) { + path = null; + } +}); + +var getMousePosition = function (e) { + return { + x: e.pageX - rect.left, + y: e.pageY - rect.top, + }; +}; + +var appendToBuffer = function (pt) { + buffer.push(pt); + while (buffer.length > bufferSize) { + buffer.shift(); + } +}; + +// Calculate the average point, starting at offset in the buffer +var getAveragePoint = function (offset) { + var len = buffer.length; + if (len % 2 === 1 || len >= bufferSize) { + var totalX = 0; + var totalY = 0; + var pt, i; + var count = 0; + for (i = offset; i < len; i++) { + count++; + pt = buffer[i]; + totalX += pt.x; + totalY += pt.y; + } + return { + x: totalX / count, + y: totalY / count, + }; + } + return null; +}; + +var updateSvgPath = function () { + var pt = getAveragePoint(0); + + if (pt) { + // Get the smoothed part of the path that will not change + strPath += " L" + pt.x + " " + pt.y; + + // Get the last part of the path (close to the current mouse position) + // This part will change if the mouse moves again + var tmpPath = ""; + for (var offset = 2; offset < buffer.length; offset += 2) { + pt = getAveragePoint(offset); + tmpPath += " L" + pt.x + " " + pt.y; + } + + // Set the complete current path coordinates + path.setAttribute("d", strPath + tmpPath); + } +}; + +// +// +// +// SAVE THE BRANCH + +const form = document.querySelector("form"); + +form.addEventListener("submit", () => { + let wrapper = document.createElement("div"); + wrapper.appendChild(svgElement); + form["content"].value = wrapper.innerHTML; + return true; +}); diff --git a/exquisite_branch/static/js/draw.js b/exquisite_branch/static/js/draw.js index 71404c4..8935639 100644 --- a/exquisite_branch/static/js/draw.js +++ b/exquisite_branch/static/js/draw.js @@ -104,23 +104,11 @@ var updateSvgPath = function () { // // SAVE THE BRANCH -const send = document.getElementById("send"); -send.addEventListener("click", (e) => saveSVG(e)); +const form = document.querySelector("form"); -async function saveSVG(e) { +form.addEventListener("submit", () => { let wrapper = document.createElement("div"); wrapper.appendChild(svgElement); - - await fetch(`${svgElement.dataset.parent}`, { - method: "POST", - redirect: "follow", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - content: wrapper.innerHTML, - parent: svgElement.dataset.parent, - branch: svgElement.dataset.branch, - }), - }).then((res) => (window.location = res.url)); -} + form["content"].value = wrapper.innerHTML; + return true; +}); diff --git a/exquisite_branch/templates/.ipynb_checkpoints/display-checkpoint.html b/exquisite_branch/templates/.ipynb_checkpoints/display-checkpoint.html new file mode 100644 index 0000000..9859a18 --- /dev/null +++ b/exquisite_branch/templates/.ipynb_checkpoints/display-checkpoint.html @@ -0,0 +1,37 @@ + + + + + + + Display + + + + + +

Exquisite Branch

+ +
+ {% for stream in streams %} +
+ {% for branch in stream %} {{branch['content'] | safe}} {%endfor%} +
+ {%endfor%} +
+ + {{colors}} + +

Branches

+
+ {% for stream in streams %} +
+ {% for branch in stream %} {{branch['content'] | safe}} {%endfor%} +
+ {%endfor%} +
+ + diff --git a/exquisite_branch/templates/.ipynb_checkpoints/draw-checkpoint.html b/exquisite_branch/templates/.ipynb_checkpoints/draw-checkpoint.html new file mode 100644 index 0000000..217937f --- /dev/null +++ b/exquisite_branch/templates/.ipynb_checkpoints/draw-checkpoint.html @@ -0,0 +1,54 @@ + + + + + + + Draw + + + + + + + + +

Draw

+
+ + +
+ +
+ + +
+ +
+ + + +
+ + diff --git a/exquisite_branch/templates/.ipynb_checkpoints/share-checkpoint.html b/exquisite_branch/templates/.ipynb_checkpoints/share-checkpoint.html new file mode 100644 index 0000000..d8312d2 --- /dev/null +++ b/exquisite_branch/templates/.ipynb_checkpoints/share-checkpoint.html @@ -0,0 +1,20 @@ + + + + + + + Share + + + + + + + + diff --git a/exquisite_branch/templates/draw.html b/exquisite_branch/templates/draw.html index e0d0adc..217937f 100644 --- a/exquisite_branch/templates/draw.html +++ b/exquisite_branch/templates/draw.html @@ -45,6 +45,10 @@ - +
+ + + +