commit 95d87f711651cee384d3821d59cf898bf2c045b0 Author: supisara Date: Fri Jun 10 17:07:13 2022 +0200 project setup diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7275bb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..539a4cf --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Workbook + +![Nice cover for the modbook](temp.jpg) + +Starting with the workbook, the idea is to have it as a visual learning aid/recorder/notebook + +TODO: nice documentation \ No newline at end of file diff --git a/static/css/global.css b/static/css/global.css new file mode 100644 index 0000000..666fc14 --- /dev/null +++ b/static/css/global.css @@ -0,0 +1,90 @@ +* { + box-sizing: border-box; +} + +html, +body { + font-family: sans-serif; +} + +a { + color: currentColor; + text-decoration: none; +} + +header a:hover { + opacity: .5; +} + +header { + width: 100%; + display: flex; + justify-content: space-between; + padding: 8px; + font-size: 32px; + +} + +header > * { + flex-shrink: 0; +} + + + +header .title { + margin: 0; + margin-right: 32px; + font-size: 32px; + font-weight: normal; + +} + +.path-slash { + margin: 0 4px; +} + +.parent { + /* color: rgb(147, 149, 161); */ +} + + +.search, .print { + position: relative; + + display: inline-block; + height: 32px; + margin-left: auto; + overflow: hidden; + flex: 0 0 32px; + transition: flex 0.3s ease-in; +} + +.search:hover{ + transition: flex 0.6s ease-out; + flex: 1 0 auto; +} + +.search svg, .print svg { + width: 32px; + height: 32px; + padding: 4px; + margin: 0; +} + +.search input { + border: none; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 32px; + outline: none; + border-bottom: 1px solid currentColor; + + font-size: 32px; + + padding: 0; + padding-left: 4px; + + background: none; +} diff --git a/static/css/home.css b/static/css/home.css new file mode 100644 index 0000000..9e907d7 --- /dev/null +++ b/static/css/home.css @@ -0,0 +1,35 @@ +.homepanel .socket { + position: absolute; +} + +.socket .plug { + display: inline-block; + width: 24px; + height: 24px; + border: 1px solid currentColor; + cursor: alias; + position: relative; + z-index: 50; + background: none; + + user-select: none; + vertical-align: middle; +} + +.plug.out { + border-radius: 50%; +} + +.socket label { + text-transform: uppercase; + line-height: 1; +} + +svg { + position: absolute; + top: 0; + left: 0; + border: 1px solid currentColor; + width: 100%; + height: 100%; +} diff --git a/static/css/patch.css b/static/css/patch.css new file mode 100644 index 0000000..6a1d7f6 --- /dev/null +++ b/static/css/patch.css @@ -0,0 +1,61 @@ +.instrument { + max-height: 100vh; + max-width: 100vw; + object-fit: contain; + margin: 0 auto; + display: block; +} + +.samples { + width: 100%; + padding: 0; +} + +.samples li { + display: flex; + width: 100%; + font-size: 32px; + padding: 8px; +} + +.samples li > * { + flex-shrink: 0; +} +.samples li:nth-child(even) { + background:#efefef; + } + +.samples li button{ + background-color: white; + border: 1px solid currentColor; + padding: 4px; + width: 32px; + height: 32px; + display: inline-block; +} + +.samples li button svg{ + width: 100%; + height: 100%; +} + +.download { + margin-left: auto; + margin-right: 16px; +} + +.samples .description { + margin: 0 8px; + flex-shrink: 1; + +} + +.print svg{ + background-color: white; + border: 1px solid currentColor; + padding: 4px; + width: 32px; + height: 32px; + display: inline-block; +} + diff --git a/static/css/patches.css b/static/css/patches.css new file mode 100644 index 0000000..e70fb7d --- /dev/null +++ b/static/css/patches.css @@ -0,0 +1,123 @@ +* { + box-sizing: border-box; +} + +html, body { + font-family: sans-serif; + +} + + +a { + color: currentColor; + text-decoration: none; +} + + + + + + +main { + padding: 0 8px; +} + + +.list { + padding: 0; + display: grid; + + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + + + gap: 16px; +} + +.card { + /* transform: skew(14deg); */ + aspect-ratio: 1; + border: 1px solid currentColor; + padding: 32px; + font-stretch: 50%; + + + + display: flex; + justify-content: center; + align-items: center; + position: relative; + + + + font-size: 32px; + text-align: center; +} + +.card:hover { + background-color: grey; +} + + +.card > * { + /* transform: skew(-28deg); */ +} + +.card svg { + width: 32px; + height: 32px; +} + +.card img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.card .overlay { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + vertical-align: middle; + display: flex; + justify-content: center; + align-items: center; + background-color: grey; + opacity: 0; +} + +.card .overlay:hover { + opacity: 1; +} + +.card .title { + font-weight: normal; +} + + + +@media (max-width: 767px){ + + + +header { + display: block; + font-size: 28px; +} + +header .title { + display: inline; + font-size: 28px; +} + + .search { + margin-top: 16px; + display: block; + } + + .search input { + font-size: 28px; + } +} + diff --git a/static/css/workbook.css b/static/css/workbook.css new file mode 100644 index 0000000..071d28b --- /dev/null +++ b/static/css/workbook.css @@ -0,0 +1,63 @@ + + +main { + padding: 0 8px; +} + +.list { + padding: 0; + display: grid; + + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + + gap: 16px; +} + +.card { + /* transform: skew(14deg); */ + aspect-ratio: 1; + border: 1px solid currentColor; + padding: 32px; + font-stretch: 50%; + + display: flex; + justify-content: center; + align-items: center; + + font-size: 32px; + text-align: center; +} + +.card:hover { + background-color: grey; +} + +.card > * { + /* transform: skew(-28deg); */ +} + +.card svg { + width: 32px; + height: 32px; +} + +@media (max-width: 767px) { + header { + display: block; + font-size: 28px; + } + + header .title { + display: inline; + font-size: 28px; + } + + .search { + margin-top: 16px; + display: block; + } + + .search input { + font-size: 28px; + } +} diff --git a/static/img/kastle-drum.svg b/static/img/kastle-drum.svg new file mode 100644 index 0000000..adf981b --- /dev/null +++ b/static/img/kastle-drum.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/kastle-v1.5.svg b/static/img/kastle-v1.5.svg new file mode 100644 index 0000000..1dc6659 --- /dev/null +++ b/static/img/kastle-v1.5.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/js/cables.js b/static/js/cables.js new file mode 100644 index 0000000..5187fa0 --- /dev/null +++ b/static/js/cables.js @@ -0,0 +1,143 @@ +// Great resource from https://stackoverflow.com/a/40700068 +// Thank you ConnorFan + +var strokeWidth = 10; +var bufferSize = 10; + +var svgElement = document.getElementById("svgElement"); +svgElement.setAttribute("viewBox", `0 0 ${svgElement.clientWidth} ${svgElement.clientHeight}`); + +var rect = svgElement.getBoundingClientRect(); +var path = null; +var strPath; +var buffer = []; // Contains the last positions of the mouse cursor +var cable; + +class Cable { + start = ""; + end = ""; + path = ""; + color = ""; + + constructor(start) { + this.start = start; + } +} + +window.addEventListener("resize", (e) => { + svgElement.setAttribute("viewBox", `0 0 ${svgElement.clientWidth} ${svgElement.clientHeight}`); +}); + +window.addEventListener("mousedown", function (e) { + let socket = e.target; + + if (socket.matches(".plug.out")) { + path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + + let color = randomColor(); + path.setAttribute("stroke", color); + path.setAttribute("stroke-width", strokeWidth); + path.setAttribute("stroke-linecap", "round"); + buffer = []; + var pt = getMousePosition(e); + appendToBuffer(pt); + strPath = "M" + pt.x + " " + pt.y; + path.setAttribute("d", strPath); + svgElement.appendChild(path); + + cable = new Cable(socket.nextElementSibling.innerHTML); + cable.color = color; + } +}); + +window.addEventListener("mousemove", function (e) { + if (path) { + appendToBuffer(getMousePosition(e)); + updateSvgPath(); + } +}); + +window.addEventListener("mouseup", (e) => appendCable(e)); +window.addEventListener("mouseleave", (e) => appendCable(e)); + +var appendCable = function (e) { + if (path) { + let socket = e.target; + if (socket.matches(".plug.in")) { + cable.end = socket.nextElementSibling.innerHTML; + cable.path = path.getAttribute("d"); + } + 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; +}; + +// ok +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); + } +}; + +// ok +var randomColor = function () { + const hue = Math.floor(Math.random() * 360); + const saturation = Math.floor(50 + Math.random() * (50 + 1)) + "%"; + const lightness = "75%"; + return "hsl(" + hue + ", " + saturation + ", " + lightness + ")"; +}; + +const enter = document.getElementById("enter"); +enter.addEventListener("mouseup", (e) => { + window.location = cable.start.toLowerCase(); +}); diff --git a/temp.jpg b/temp.jpg new file mode 100644 index 0000000..30a75d5 Binary files /dev/null and b/temp.jpg differ diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..10e1422 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,50 @@ + + + + + + + + modbook + + +
+ + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+
+ + diff --git a/templates/patch.html b/templates/patch.html new file mode 100644 index 0000000..bc53d66 --- /dev/null +++ b/templates/patch.html @@ -0,0 +1,196 @@ + + + + + {{title}} + + + + +
+ Home + / + Workbook + / + {{instrument}} + / +

{{title}}

+ + +
+ +
+ Patch 1 + +
+ + diff --git a/templates/patches.html b/templates/patches.html new file mode 100644 index 0000000..06b3618 --- /dev/null +++ b/templates/patches.html @@ -0,0 +1,97 @@ + + + + + {{instrument}} + + + + +
+ Home + + / + + Workbook + + / + +

{{instrument}}

+ +
+ +
+ +
+ + + + + + + diff --git a/templates/workbook.html b/templates/workbook.html new file mode 100644 index 0000000..f488c2d --- /dev/null +++ b/templates/workbook.html @@ -0,0 +1,60 @@ + + + + + Workbook + + + + + + + + + +
+ Home + + / + +

Workbook

+ +
+ +
+ +
+ + + + + + + diff --git a/workbook.py b/workbook.py new file mode 100644 index 0000000..e6f255a --- /dev/null +++ b/workbook.py @@ -0,0 +1,24 @@ +from flask import Flask, render_template + +app = Flask(__name__) + +@app.route("/") +def home(): + return render_template('home.html') + +@app.route("/workbook") +def workbook(): + return render_template('workbook.html') + +@app.route("/workbook/") +def patches(instrument): + return render_template('patches.html', instrument=instrument) + + +@app.route("/workbook//") +def patch(instrument, title): + return render_template('patch.html', instrument=instrument, title=title) + + + +app.run(port=3000, debug=True) \ No newline at end of file