From 031b6f736187efdc64c525a40c687698701e73e1 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 28 Sep 2019 13:53:02 +0200 Subject: Initial webapp design --- webapp/job_processor.py | 34 + webapp/job_queue.py | 77 + webapp/pogojig.cfg | 4 + webapp/pogojig.py | 111 + webapp/static/3d_models.png | Bin 0 -> 151956 bytes webapp/static/arrow-small.png | Bin 0 -> 22231 bytes webapp/static/arrow.png | Bin 0 -> 74468 bytes webapp/static/bg-gears.jpg | Bin 0 -> 349760 bytes webapp/static/bg.svg | 47 + webapp/static/bubble1-small.png | Bin 0 -> 84771 bytes webapp/static/bubble1.png | Bin 0 -> 84771 bytes webapp/static/bubble2-small.png | Bin 0 -> 239804 bytes webapp/static/bubble2.png | Bin 0 -> 105129 bytes webapp/static/cad_example.svg | 587 + webapp/static/favicon-1024.jpg | Bin 0 -> 72859 bytes webapp/static/favicon-512.jpg | Bin 0 -> 93827 bytes webapp/static/favicon-512.png | Bin 0 -> 321533 bytes webapp/static/fonts/SourceSansPro-Black.ttf | Bin 0 -> 265612 bytes webapp/static/fonts/SourceSansPro-Black.woff2 | Bin 0 -> 78644 bytes webapp/static/fonts/SourceSansPro-BlackItalic.ttf | Bin 0 -> 93924 bytes .../static/fonts/SourceSansPro-BlackItalic.woff2 | Bin 0 -> 33996 bytes webapp/static/fonts/SourceSansPro-Bold.ttf | Bin 0 -> 267388 bytes webapp/static/fonts/SourceSansPro-Bold.woff2 | Bin 0 -> 81992 bytes webapp/static/fonts/SourceSansPro-BoldItalic.ttf | Bin 0 -> 94132 bytes webapp/static/fonts/SourceSansPro-BoldItalic.woff2 | Bin 0 -> 34900 bytes webapp/static/fonts/SourceSansPro-ExtraLight.ttf | Bin 0 -> 267368 bytes webapp/static/fonts/SourceSansPro-ExtraLight.woff2 | Bin 0 -> 79152 bytes .../fonts/SourceSansPro-ExtraLightItalic.ttf | Bin 0 -> 95256 bytes .../fonts/SourceSansPro-ExtraLightItalic.woff2 | Bin 0 -> 33588 bytes webapp/static/fonts/SourceSansPro-Italic.ttf | Bin 0 -> 94816 bytes webapp/static/fonts/SourceSansPro-Italic.woff2 | Bin 0 -> 34892 bytes webapp/static/fonts/SourceSansPro-Light.ttf | Bin 0 -> 268588 bytes webapp/static/fonts/SourceSansPro-Light.woff2 | Bin 0 -> 82696 bytes webapp/static/fonts/SourceSansPro-LightItalic.ttf | Bin 0 -> 95128 bytes .../static/fonts/SourceSansPro-LightItalic.woff2 | Bin 0 -> 34808 bytes webapp/static/fonts/SourceSansPro-Regular.ttf | Bin 0 -> 269108 bytes webapp/static/fonts/SourceSansPro-Regular.woff2 | Bin 0 -> 83248 bytes webapp/static/fonts/SourceSansPro-SemiBold.ttf | Bin 0 -> 268280 bytes webapp/static/fonts/SourceSansPro-SemiBold.woff2 | Bin 0 -> 82444 bytes .../static/fonts/SourceSansPro-SemiBoldItalic.ttf | Bin 0 -> 94512 bytes .../fonts/SourceSansPro-SemiBoldItalic.woff2 | Bin 0 -> 34900 bytes webapp/static/fonts/Source_Sans_Pro.zip | Bin 0 -> 983436 bytes webapp/static/footer_love.svg | 125 + webapp/static/index.html | 66 + webapp/static/pogojig-title.png | Bin 0 -> 217635 bytes webapp/static/realistic_render.png | Bin 0 -> 275105 bytes webapp/static/style.css | 176 + webapp/static/workflow.svg | 1596 +++ .../static/workflow.svg.2019_09_27_14_18_13.0.svg | 12004 +++++++++++++++++++ webapp/static/workflow2.svg | 1582 +++ webapp/static/workflow3.svg | 1596 +++ webapp/templates/jigerator.html | 61 + 52 files changed, 18066 insertions(+) create mode 100644 webapp/job_processor.py create mode 100644 webapp/job_queue.py create mode 100644 webapp/pogojig.cfg create mode 100644 webapp/pogojig.py create mode 100644 webapp/static/3d_models.png create mode 100644 webapp/static/arrow-small.png create mode 100644 webapp/static/arrow.png create mode 100644 webapp/static/bg-gears.jpg create mode 100644 webapp/static/bg.svg create mode 100644 webapp/static/bubble1-small.png create mode 100644 webapp/static/bubble1.png create mode 100644 webapp/static/bubble2-small.png create mode 100644 webapp/static/bubble2.png create mode 100644 webapp/static/cad_example.svg create mode 100644 webapp/static/favicon-1024.jpg create mode 100644 webapp/static/favicon-512.jpg create mode 100644 webapp/static/favicon-512.png create mode 100644 webapp/static/fonts/SourceSansPro-Black.ttf create mode 100644 webapp/static/fonts/SourceSansPro-Black.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-BlackItalic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-BlackItalic.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-Bold.ttf create mode 100644 webapp/static/fonts/SourceSansPro-Bold.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-BoldItalic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-BoldItalic.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-ExtraLight.ttf create mode 100644 webapp/static/fonts/SourceSansPro-ExtraLight.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-ExtraLightItalic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-ExtraLightItalic.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-Italic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-Italic.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-Light.ttf create mode 100644 webapp/static/fonts/SourceSansPro-Light.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-LightItalic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-LightItalic.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-Regular.ttf create mode 100644 webapp/static/fonts/SourceSansPro-Regular.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-SemiBold.ttf create mode 100644 webapp/static/fonts/SourceSansPro-SemiBold.woff2 create mode 100644 webapp/static/fonts/SourceSansPro-SemiBoldItalic.ttf create mode 100644 webapp/static/fonts/SourceSansPro-SemiBoldItalic.woff2 create mode 100644 webapp/static/fonts/Source_Sans_Pro.zip create mode 100644 webapp/static/footer_love.svg create mode 100644 webapp/static/index.html create mode 100644 webapp/static/pogojig-title.png create mode 100644 webapp/static/realistic_render.png create mode 100644 webapp/static/style.css create mode 100644 webapp/static/workflow.svg create mode 100644 webapp/static/workflow.svg.2019_09_27_14_18_13.0.svg create mode 100644 webapp/static/workflow2.svg create mode 100644 webapp/static/workflow3.svg create mode 100644 webapp/templates/jigerator.html diff --git a/webapp/job_processor.py b/webapp/job_processor.py new file mode 100644 index 0000000..883d1e6 --- /dev/null +++ b/webapp/job_processor.py @@ -0,0 +1,34 @@ + +import signal +import subprocess +import logging +import itertools + +from job_queue import JobQueue + + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('queue', help='job queue sqlite3 database file') + parser.add_argument('--loglevel', '-l', default='info') + args = parser.parse_args() + + numeric_level = getattr(logging, args.loglevel.upper(), None) + if not isinstance(numeric_level, int): + raise ValueError('Invalid log level: %s' % loglevel) + logging.basicConfig(level=numeric_level) + + job_queue = JobQueue(args.queue) + + signal.signal(signal.SIGALRM, lambda *args: None) # Ignore incoming alarm signals while processing jobs + signal.setitimer(signal.ITIMER_REAL, 0.001, 1) + while signal.sigwait([signal.SIGALRM, signal.SIGINT]) == signal.SIGALRM: + logging.debug('Checking for jobs') + for job in job_queue.job_iter('render'): + logging.info(f'Processing {job.type} job {job.id} session {job["session_id"]} from {job.client} submitted {job.created}') + with job: + job.result = subprocess.call(['sudo', '/usr/local/sbin/pogojig_render.sh', job['session_id']]) + logging.info(f'Finishied processing {job.type} job {job.id}') + logging.info('Caught SIGINT. Exiting.') + diff --git a/webapp/job_queue.py b/webapp/job_queue.py new file mode 100644 index 0000000..62ba398 --- /dev/null +++ b/webapp/job_queue.py @@ -0,0 +1,77 @@ + +import json +import sqlite3 + +class JobQueue: + def __init__(self, dbfile): + self.dbfile = dbfile + self.db = sqlite3.connect(dbfile, check_same_thread=False) + self.db.row_factory = sqlite3.Row + with self.db as conn: + conn.execute('''CREATE TABLE IF NOT EXISTS jobs + (id INTEGER PRIMARY KEY, + type TEXT, + params TEXT, + client TEXT, + result INTEGER DEFAULT NULL, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + consumed DATETIME DEFAULT NULL, + aborted DATETIME DEFAULT NULL, + finished DATETIME DEFAULT NULL);''') + + def enqueue(self, task_type:str, client, **params): + """ Enqueue a job of the given type with the given params. Returns the new job ID. """ + with self.db as conn: + return conn.execute('INSERT INTO jobs(type, client, params) VALUES (?, ?, ?)', + (task_type, client, json.dumps(params))).lastrowid + + def pop(self, task_type): + """ Fetch the next job of the given type. Returns a sqlite3.Row object of the job or None if no jobs of the given + type are queued. """ + with self.db as conn: + job = conn.execute('SELECT * FROM jobs WHERE type=? AND consumed IS NULL AND aborted IS NULL ORDER BY created ASC LIMIT 1', + (task_type,)).fetchone() + if job is None: + return None + + # Atomically commit to this job + conn.execute('UPDATE jobs SET consumed=datetime("now") WHERE id=?', (job['id'],)) + + return Job(self.db, job) + + def job_iter(self, task_type): + return iter(lambda: self.pop(task_type), None) + + def __getitem__(self, key): + """ Return the job with the given ID, or raise a KeyError if the key cannot be found. """ + with self.db as conn: + job = conn.execute('SELECT * FROM jobs WHERE id=?', (key,)).fetchone() + if job is None: + raise KeyError(f'Unknown job ID "{key}"') + + return Job(self.db, job) + +class Job(dict): + def __init__(self, db, row): + super().__init__(json.loads(row['params'])) + self._db = db + self._row = row + self.id = row['id'] + self.type = row['type'] + self.client = row['client'] + self.created = row['created'] + self.consumed = row['consumed'] + self.finished = row['finished'] + self.result = row['result'] + + def __enter__(self): + return self + + def __exit__(self, _exc_type, _exc_val, _exc_tb): + with self._db as conn: + conn.execute('UPDATE jobs SET finished=datetime("now"), result=? WHERE id=?', (self.result, self.id,)) + + def abort(self, job_id): + with self.db as conn: + conn.execute('UPDATE jobs SET aborted=datetime("now") WHERE id=?', (self.id,)) + diff --git a/webapp/pogojig.cfg b/webapp/pogojig.cfg new file mode 100644 index 0000000..2d45385 --- /dev/null +++ b/webapp/pogojig.cfg @@ -0,0 +1,4 @@ +MAX_CONTENT_LENGTH=10000000 +SECRET_KEY="FIXME: CHANGE THIS KEY" +UPLOAD_PATH="/var/cache/pogojig/upload" +JOB_QUEUE_DB="/var/cache/pogojig/job_queue.sqlite3" diff --git a/webapp/pogojig.py b/webapp/pogojig.py new file mode 100644 index 0000000..a7201d0 --- /dev/null +++ b/webapp/pogojig.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +# TODO setup webserver user disk quota + +import tempfile +import uuid +from functools import wraps +from os import path +import os +import sqlite3 + +from flask import Flask, url_for, redirect, session, make_response, render_template, request, send_file, abort, flash +from flask_wtf import FlaskForm +from flask_wtf.file import FileField, FileRequired +from wtforms.fields import RadioField +from wtforms.validators import DataRequired +from werkzeug.utils import secure_filename + +from job_queue import JobQueue + +app = Flask(__name__, static_url_path='/static') +app.config.from_envvar('POGOJIG_SETTINGS') + +class UploadForm(FlaskForm): + upload_file = FileField(validators=[DataRequired()]) + +class ResetForm(FlaskForm): + pass + +job_queue = JobQueue(app.config['JOB_QUEUE_DB']) + +def tempfile_path(namespace): + """ Return a path for a per-session temporary file identified by the given namespace. Create the session tempfile + dir if necessary. The application tempfile dir is controlled via the upload_path config value and not managed by + this function. """ + sess_tmp = path.join(app.config['UPLOAD_PATH'], session['session_id']) + os.makedirs(sess_tmp, exist_ok=True) + return path.join(sess_tmp, namespace) + +def require_session_id(fun): + @wraps(fun) + def wrapper(*args, **kwargs): + if 'session_id' not in session: + session['session_id'] = str(uuid.uuid4()) + return fun(*args, **kwargs) + return wrapper + +@app.route('/') +def index(): + return app.send_static_file('index.html') + +@app.route('/jigerator') +@require_session_id +def jigerator(): + forms = { + 'svg_form': UploadForm(), + 'reset_form': ResetForm() } + + if 'render_job' in session: + job = job_queue[session['render_job']] + if job.finished: + if job.result != 0: + flash(f'Error processing SVG file', 'success') # FIXME make this an error, add CSS + del session['render_job'] + + r = make_response(render_template('jigerator.html', has_renders=path.isfile(tempfile_path('output.zip')), **forms)) + if 'render_job' in session: + r.headers.set('refresh', '10') + return r + +# NOTES about the SVG file upload routines +# * The maximum upload size is limited by the MAX_CONTENT_LENGTH config setting. +# * The uploaded files are deleted after a while by systemd tmpfiles.d +# TODO: validate this setting applies *after* gzip transport compression + +def render(): + if 'render_job' in session: + job_queue[session['render_job']].abort() + session['render_job'] = job_queue.enqueue('render', + session_id=session['session_id'], + client=request.remote_addr) + +@app.route('/upload/svg', methods=['POST']) +@require_session_id +def upload_svg(): + upload_form = UploadForm() + if upload_form.validate_on_submit(): + f = upload_form.upload_file.data + f.save(tempfile_path('input.svg')) + session['filename'] = secure_filename(f.filename) # Cache filename for later download + + render() + flash(f'SVG file successfully uploaded.', 'success') + return redirect(url_for('jigerator')) + +@app.route('/render/download') +def render_download(): + return send_file(tempfile_path(f'renders.zip'), + mimetype='application/zip', + as_attachment=True, + attachment_filename=f'{path.splitext(session["filename"])[0]}_pogojig.zip') + +@app.route('/session_reset', methods=['POST']) +@require_session_id +def session_reset(): + if 'render_job' in session: + job_queue[session['render_job']].abort() + session.clear() + flash('Session reset', 'success'); + return redirect(url_for('jigerator')) + diff --git a/webapp/static/3d_models.png b/webapp/static/3d_models.png new file mode 100644 index 0000000..4ee3f8d Binary files /dev/null and b/webapp/static/3d_models.png differ diff --git a/webapp/static/arrow-small.png b/webapp/static/arrow-small.png new file mode 100644 index 0000000..fbc542c Binary files /dev/null and b/webapp/static/arrow-small.png differ diff --git a/webapp/static/arrow.png b/webapp/static/arrow.png new file mode 100644 index 0000000..0d86748 Binary files /dev/null and b/webapp/static/arrow.png differ diff --git a/webapp/static/bg-gears.jpg b/webapp/static/bg-gears.jpg new file mode 100644 index 0000000..820ec57 Binary files /dev/null and b/webapp/static/bg-gears.jpg differ diff --git a/webapp/static/bg.svg b/webapp/static/bg.svg new file mode 100644 index 0000000..13168e7 --- /dev/null +++ b/webapp/static/bg.svg @@ -0,0 +1,47 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/webapp/static/bubble1-small.png b/webapp/static/bubble1-small.png new file mode 100644 index 0000000..fb90adf Binary files /dev/null and b/webapp/static/bubble1-small.png differ diff --git a/webapp/static/bubble1.png b/webapp/static/bubble1.png new file mode 100644 index 0000000..fb90adf Binary files /dev/null and b/webapp/static/bubble1.png differ diff --git a/webapp/static/bubble2-small.png b/webapp/static/bubble2-small.png new file mode 100644 index 0000000..3085149 Binary files /dev/null and b/webapp/static/bubble2-small.png differ diff --git a/webapp/static/bubble2.png b/webapp/static/bubble2.png new file mode 100644 index 0000000..55bad9a Binary files /dev/null and b/webapp/static/bubble2.png differ diff --git a/webapp/static/cad_example.svg b/webapp/static/cad_example.svg new file mode 100644 index 0000000..f0b69f0 --- /dev/null +++ b/webapp/static/cad_example.svg @@ -0,0 +1,587 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webapp/static/favicon-1024.jpg b/webapp/static/favicon-1024.jpg new file mode 100644 index 0000000..df5eecd Binary files /dev/null and b/webapp/static/favicon-1024.jpg differ diff --git a/webapp/static/favicon-512.jpg b/webapp/static/favicon-512.jpg new file mode 100644 index 0000000..f97dc04 Binary files /dev/null and b/webapp/static/favicon-512.jpg differ diff --git a/webapp/static/favicon-512.png b/webapp/static/favicon-512.png new file mode 100644 index 0000000..17b244d Binary files /dev/null and b/webapp/static/favicon-512.png differ diff --git a/webapp/static/fonts/SourceSansPro-Black.ttf b/webapp/static/fonts/SourceSansPro-Black.ttf new file mode 100644 index 0000000..4569f24 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Black.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-Black.woff2 b/webapp/static/fonts/SourceSansPro-Black.woff2 new file mode 100644 index 0000000..c37f4aa Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Black.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-BlackItalic.ttf b/webapp/static/fonts/SourceSansPro-BlackItalic.ttf new file mode 100644 index 0000000..3477e16 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-BlackItalic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-BlackItalic.woff2 b/webapp/static/fonts/SourceSansPro-BlackItalic.woff2 new file mode 100644 index 0000000..06289d0 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-BlackItalic.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-Bold.ttf b/webapp/static/fonts/SourceSansPro-Bold.ttf new file mode 100644 index 0000000..1f430e2 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Bold.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-Bold.woff2 b/webapp/static/fonts/SourceSansPro-Bold.woff2 new file mode 100644 index 0000000..f23489d Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Bold.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-BoldItalic.ttf b/webapp/static/fonts/SourceSansPro-BoldItalic.ttf new file mode 100644 index 0000000..98089fd Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-BoldItalic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-BoldItalic.woff2 b/webapp/static/fonts/SourceSansPro-BoldItalic.woff2 new file mode 100644 index 0000000..987f9df Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-BoldItalic.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-ExtraLight.ttf b/webapp/static/fonts/SourceSansPro-ExtraLight.ttf new file mode 100644 index 0000000..caf2673 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-ExtraLight.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-ExtraLight.woff2 b/webapp/static/fonts/SourceSansPro-ExtraLight.woff2 new file mode 100644 index 0000000..1fe2cf6 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-ExtraLight.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-ExtraLightItalic.ttf b/webapp/static/fonts/SourceSansPro-ExtraLightItalic.ttf new file mode 100644 index 0000000..b0362f3 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-ExtraLightItalic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-ExtraLightItalic.woff2 b/webapp/static/fonts/SourceSansPro-ExtraLightItalic.woff2 new file mode 100644 index 0000000..7652cac Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-ExtraLightItalic.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-Italic.ttf b/webapp/static/fonts/SourceSansPro-Italic.ttf new file mode 100644 index 0000000..e7b9182 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Italic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-Italic.woff2 b/webapp/static/fonts/SourceSansPro-Italic.woff2 new file mode 100644 index 0000000..34465cd Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Italic.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-Light.ttf b/webapp/static/fonts/SourceSansPro-Light.ttf new file mode 100644 index 0000000..348871a Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Light.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-Light.woff2 b/webapp/static/fonts/SourceSansPro-Light.woff2 new file mode 100644 index 0000000..a48f1c1 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Light.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-LightItalic.ttf b/webapp/static/fonts/SourceSansPro-LightItalic.ttf new file mode 100644 index 0000000..989dc8e Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-LightItalic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-LightItalic.woff2 b/webapp/static/fonts/SourceSansPro-LightItalic.woff2 new file mode 100644 index 0000000..ed2a23a Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-LightItalic.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-Regular.ttf b/webapp/static/fonts/SourceSansPro-Regular.ttf new file mode 100644 index 0000000..b422bf4 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Regular.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-Regular.woff2 b/webapp/static/fonts/SourceSansPro-Regular.woff2 new file mode 100644 index 0000000..3362d40 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-Regular.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-SemiBold.ttf b/webapp/static/fonts/SourceSansPro-SemiBold.ttf new file mode 100644 index 0000000..2908e0d Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-SemiBold.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-SemiBold.woff2 b/webapp/static/fonts/SourceSansPro-SemiBold.woff2 new file mode 100644 index 0000000..ffa2c0e Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-SemiBold.woff2 differ diff --git a/webapp/static/fonts/SourceSansPro-SemiBoldItalic.ttf b/webapp/static/fonts/SourceSansPro-SemiBoldItalic.ttf new file mode 100644 index 0000000..990cf91 Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-SemiBoldItalic.ttf differ diff --git a/webapp/static/fonts/SourceSansPro-SemiBoldItalic.woff2 b/webapp/static/fonts/SourceSansPro-SemiBoldItalic.woff2 new file mode 100644 index 0000000..5e8d28b Binary files /dev/null and b/webapp/static/fonts/SourceSansPro-SemiBoldItalic.woff2 differ diff --git a/webapp/static/fonts/Source_Sans_Pro.zip b/webapp/static/fonts/Source_Sans_Pro.zip new file mode 100644 index 0000000..45aa3ba Binary files /dev/null and b/webapp/static/fonts/Source_Sans_Pro.zip differ diff --git a/webapp/static/footer_love.svg b/webapp/static/footer_love.svg new file mode 100644 index 0000000..9fc5b67 --- /dev/null +++ b/webapp/static/footer_love.svg @@ -0,0 +1,125 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webapp/static/index.html b/webapp/static/index.html new file mode 100644 index 0000000..586f64d --- /dev/null +++ b/webapp/static/index.html @@ -0,0 +1,66 @@ + + + + Pogojig Test Fixture Generator + + + + + + +
+
+ Pogojig +

+ Pogojig is a tool to generate pogo pin test fixtures for printed circuit board manufacturing and development. + Pogojig generates a 3d printable board holder with holes for mounting pogo pins, along with a matching KiCAD + PCB project for a pogo pin breakout and mounting PCB. + + You can start with either Gerber files exported from any PCB toolchain, or you can do a free-form layout using + the static Inkscape SVG template if you + wan to work from construction drawings, scanned or photographed PCBs etc. +

+
+ +
+
+ 1. Convert your Gerbers to an SVG template and draw pogo pins, mounting holes and cutouts + into the template. Don't have gerbers? Start with an + empty template. +
+
+
click to open
+ Pogospace +
+
+ +
+ Gerber files + arrow pointing right + SVG blueprint + arrow pointing right + 3D models of matching plastic holder and base PCB +
+ +
+
+ 2. Upload your SVG to generate STL and OpenSCAD files for the plastic holder, and KiCAD and + DXF files for the base PCB. +
+
+
click to open
+ Jigerator +
+
+ + +
+ + diff --git a/webapp/static/pogojig-title.png b/webapp/static/pogojig-title.png new file mode 100644 index 0000000..0e378b1 Binary files /dev/null and b/webapp/static/pogojig-title.png differ diff --git a/webapp/static/realistic_render.png b/webapp/static/realistic_render.png new file mode 100644 index 0000000..ac9d00b Binary files /dev/null and b/webapp/static/realistic_render.png differ diff --git a/webapp/static/style.css b/webapp/static/style.css new file mode 100644 index 0000000..da272af --- /dev/null +++ b/webapp/static/style.css @@ -0,0 +1,176 @@ + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(fonts/SourceSansPro-Light.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/SourceSansPro-Regular.woff2) format('woff2'); +} + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(fonts/SourceSansPro-Bold.woff2) format('woff2'); +} + +html { + background: #2d2829; + background-image: url(bg.svg); + color: #ffffff; + font-family: 'Source Sans Pro'; + font-size: 14pt; + font-weight: 300; +} + +a:active, a:hover, a:visited, a:link { + color: #fff; + font-weight: 400; +} + + +body { + display: flex; + flex-direction: column; + align-items: center; + margin: 0 0 0 0; + padding: 3mm 3mm 3mm 3mm; +} + +.layout-container { + display: flex; + flex-direction: column; + align-items: center; + width: 38em; + max-width: 100%; +} + + +.header { + text-align: center; +} + +.header > img.title { + width: 100%; + padding-top: 50px; + padding-bottom: 50px; +} + +.header > .blurb { + text-align: justify; + hyphens: auto; + padding-bottom: 50px; +} + + +.annot { + display: flex; + align-items: center; + align-content: start; +} + +.annot.top { + align-items: end; + flex-direction: row-reverse; + align-content: start; +} + +.annot.bottom { + align-items: start; + flex-direction: row; +} + +.annot.top > .desc { + padding-left: 1em; + padding-bottom: 2em; + max-width: 60%; +} + +.annot.bottom > .desc { + padding-right: 1em; + padding-top: 4.5em; + max-width: 60%; +} + +.annot > .bubble { + max-width: 30%; + background-size: contain; + background-repeat: no-repeat; + text-align: center; + font-size: .7rem; +} + +.annot.top > .bubble { + background-image: url(bubble1-small.png); + padding: 2em 2em 5em 2em; +} + +.annot.bottom > .bubble { + background-image: url(bubble2-small.png); + padding: 7em 2em 5em 2em; +} + +a.btn { + display: block; + font-weight: 700; + background-color: #b50000; + border-radius: 0.5em; + padding: .4em 1em .4em 1em; + margin-top: .2em; +} + +a.btn:active, a.btn:hover, a.btn:visited, a.btn:link { + text-decoration: none; +} + + +.workflow-images { + display: flex; + align-items: center; + width: 100%; +} + +.workflow-images > .gerber { + width: 220px; +} + +.workflow-images > .svg { + width: 300px; +} + +.workflow-images > .models { + width: 280px; +} + +.workflow-images > .arrow { + width: 120px +} + + +.footer { + opacity: 0.5; + text-align: center; + padding-top: 5em; +} + +.footer > img { + padding-bottom: .5em; +} + +.footer > a { + display: block; +} + +.footer > .copyright { + padding-top: 1em; +} + diff --git a/webapp/static/workflow.svg b/webapp/static/workflow.svg new file mode 100644 index 0000000..2bce5b0 --- /dev/null +++ b/webapp/static/workflow.svg @@ -0,0 +1,1596 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SVG template + Gerber Gerber + SVG template + STL & KiCAD PCB STL & KiCAD PCB + + + + + + + + + + diff --git a/webapp/static/workflow.svg.2019_09_27_14_18_13.0.svg b/webapp/static/workflow.svg.2019_09_27_14_18_13.0.svg new file mode 100644 index 0000000..31d8a80 --- /dev/null +++ b/webapp/static/workflow.svg.2019_09_27_14_18_13.0.svg @@ -0,0 +1,12004 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webapp/static/workflow2.svg b/webapp/static/workflow2.svg new file mode 100644 index 0000000..db78e6f --- /dev/null +++ b/webapp/static/workflow2.svg @@ -0,0 +1,1582 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gerber SVG template STL & KiCAD PCB Gerber SVG template STL & KiCAD PCB + + + + + + + + + diff --git a/webapp/static/workflow3.svg b/webapp/static/workflow3.svg new file mode 100644 index 0000000..5610a7c --- /dev/null +++ b/webapp/static/workflow3.svg @@ -0,0 +1,1596 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SVG template + Gerber Gerber + SVG template + STL & KiCAD PCB STL & KiCAD PCB + + + + + + + + + + diff --git a/webapp/templates/jigerator.html b/webapp/templates/jigerator.html new file mode 100644 index 0000000..5ad949b --- /dev/null +++ b/webapp/templates/jigerator.html @@ -0,0 +1,61 @@ + + + + Pogojig SVG Upload + + + + + + +
+
+ Pogojig +
+ + {% with messages = get_flashed_messages(with_categories=True) %} + {% if messages %} +
+ {% for category, message in messages %} +
{{ message }}
+ {% endfor %} +
+ {% endif %} + {% endwith %} + +
{{reset_form.csrf_token}}
+ +
+
+ {{svg_form.csrf_token}} +
+
+
Upload completed SVG file:
+ +
+
+ + +
+
+ + {% if 'render_job' in session or has_renders %} +
+ {% if 'render_job' in session %} +
+
+
Processing...
+
(this may take several minutes!)
+
+ {% else %} + + {% endif %} +
+ {% endif %} {# render job #} +
+ + -- cgit