From 8b4a97bf738304ca63b7e6b64df5a50d22d3a113 Mon Sep 17 00:00:00 2001 From: Andrew Simonson Date: Sun, 29 Jan 2023 18:04:16 -0600 Subject: [PATCH] simulate Single Page App with websockets --- flask.conf | 2 +- gunicorn.conf | 2 +- src/app.py | 81 +++++++++++++++++++++++------------- src/requirements.txt | Bin 930 -> 1366 bytes src/static/css/head.css | 2 +- src/static/js/responsive.js | 23 ++++++++++ src/templates/about.html | 10 ++--- src/templates/error.html | 2 +- src/templates/header.html | 23 +++++----- src/templates/home.html | 11 +++-- src/templates/projects.html | 6 +-- 11 files changed, 105 insertions(+), 57 deletions(-) diff --git a/flask.conf b/flask.conf index ea4d07c..218e6d6 100644 --- a/flask.conf +++ b/flask.conf @@ -7,7 +7,7 @@ server { listen 8080; server_name asimonson.com; - add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' *.chesscomfiles.com *.chess.com *.googletagmanager.com cdn.jsdelivr.net www.google-analytics.com ajax.googleapis.com;"; + add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' *.cloudflare.com *.chesscomfiles.com *.chess.com *.googletagmanager.com cdn.jsdelivr.net www.google-analytics.com ajax.googleapis.com;"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options 'nosniff'; add_header X-Frame-Options 'SAMEORIGIN'; diff --git a/gunicorn.conf b/gunicorn.conf index 6412df9..334b24e 100644 --- a/gunicorn.conf +++ b/gunicorn.conf @@ -1,3 +1,3 @@ [program:gunicorn] -command=/usr/bin/gunicorn app:app -b localhost:5000 +command=/usr/bin/gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker app:app -b localhost:5000 directory=/deploy/app diff --git a/src/app.py b/src/app.py index 903cfbc..43c4f1e 100644 --- a/src/app.py +++ b/src/app.py @@ -1,44 +1,62 @@ import flask from flask_minify import Minify +from flask_socketio import SocketIO import json -proj = json.load(open('./static/json/projects.json', 'r')) -timeline = json.load(open('./static/json/timeline.json', 'r')) +proj = json.load(open("./static/json/projects.json", "r")) +timeline = json.load(open("./static/json/timeline.json", "r")) +pages = { + "home": { + "template": "home.html", + "title": "Andrew Simonson - Portfolio Home", + "description": "Andrew Simonson's Digital Portfolio home", + "canonical": "", + }, + "projects": { + "template": "projects.html", + "projects": proj, + "title": "Andrew Simonson - Projects", + "description": "Recent projects by Andrew Simonson on his lovely portfolio website :)", + "canonical": "projects", + }, + "about": { + "template": "about.html", + "timeline": timeline, + "title": "Andrew Simonson - About Me", + "description": "About Andrew Simonson", + "canonical": "about", + }, +} app = flask.Flask(__name__) Minify(app=app, html=True, js=True, cssless=True) +socketio = SocketIO(app) + + +@socketio.on("goto") +def goto(location): + sid = flask.request.sid + pagevars = pages[location] + output = [location, flask.render_template(pagevars["template"], var=pagevars), pagevars['title']] + socketio.emit("goto", output, to=sid) @app.route("/") def home(): - return flask.render_template( - "home.html", - title="Andrew Simonson - Portfolio Home", - description="Andrew Simonson's Digital portfolio home", - canonical="", - ) - - -@app.route("/about") -def about(): - return flask.render_template( - "about.html", - timeline=timeline, - title="Andrew Simonson - About Me", - description="About Andrew Simonson", - canonical="about", - ) + pagevars = pages["home"] + return flask.render_template("header.html", var=pagevars) @app.route("/projects") def projects(): - return flask.render_template( - "projects.html", - projects=proj, - title="Andrew Simonson - Projects", - description="Recent projects by Andrew Simonson on his lovely portfolio website :)", - canonical="projects", - ) + pagevars = pages["projects"] + return flask.render_template("header.html", var=pagevars) + + +@app.route("/about") +def about(): + pagevars = pages["about"] + return flask.render_template("header.html", var=pagevars) @app.route("/resume") @@ -54,9 +72,16 @@ def page404(e): try: message = e.length finally: + pagevars = { + "template": "error.html", + "title": f"{eCode} - Simonson", + "description": "Error on Andrew Simonson's Digital Portfolio", + "canonical": "404", + } return ( flask.render_template( - "error.html", + "header.html", + var=pagevars, error=eCode, message=message, title=f"{eCode} - Simonson Portfolio", @@ -75,4 +100,4 @@ if __name__ == "__main__": import sass sass.compile(dirname=("static/scss", "static/css"), output_style="compressed") - app.run(debug=True) + socketio.run(app) diff --git a/src/requirements.txt b/src/requirements.txt index 1246f6ba6cccf7e63d1958116fba21bb77ccc6c9..5e1ed2b15fa0695af05da0ea667d125edf78b98b 100644 GIT binary patch delta 439 zcmY+Au}*_v6orp0CM1rgdlN^9Agytzqlr^Z9GxfvB_&9Zw5dx+XVSslH*j+BJ^BhA zdc=($k!80pBi3!goY`8o&9Gt;KW!#=eh^UaRqwgcR ztDE=D9a8vs#R3){@j}P~Awl<;s$7IuELTx6drMZ$1gp { + pagename = page[0]; + content = page[1]; + let root = document.getElementById('root'); + root.innerHTML = content; + root.querySelectorAll("script").forEach(x => { + eval(x.innerHTML); + }); + document.querySelector('title').textContent = page[2]; + if (pagename == 'home') pagename = '/'; + history.pushState(null, null, pagename); +}); \ No newline at end of file diff --git a/src/templates/about.html b/src/templates/about.html index 8b5b006..933371a 100644 --- a/src/templates/about.html +++ b/src/templates/about.html @@ -1,4 +1,4 @@ -{% extends "header.html" %} {% block content %} +{% block content %}
@@ -41,10 +41,10 @@

Skills

{% from 'partials/skills.html' import skills %} - {{ skills([ "Python", "JavaScript", "Java", "C", "C++", "MIPS Assembly", + {{ skills([ "Python", "JavaScript", "Java", "C", "C++", "R", "MIPS Assembly", "Processing", "P5.js", "SQL", "SQLite", "PostgreSQL", "SQLAlchemy", "HTML", "CSS", "Docker", "LaTeX", "ArcGIS", "Git", "Github", "Linux", - "OKD4", "Kubernetes", "Angular", "Flask", "Jinja", "DOM Scraping", + "OKD4", "Kubernetes", "Openshift", "Angular", "Flask", "Jinja", "DOM Scraping", "Google API", "React", "Node.js", "ArcGIS", ]) }}
@@ -121,8 +121,8 @@
{% from 'partials/timeline.html' import timeitem %} - {% for i in timeline %} - {{ timeitem(i, timeline[i]["classes"], timeline[i]["date"], timeline[i]["content"])}} + {% for i in var["timeline"] %} + {{ timeitem(i, var["timeline"][i]["classes"], var["timeline"][i]["date"], var["timeline"][i]["content"])}} {% endfor %}
diff --git a/src/templates/error.html b/src/templates/error.html index bc962ec..d94850c 100644 --- a/src/templates/error.html +++ b/src/templates/error.html @@ -1,4 +1,4 @@ -{% extends "header.html" %} {% block content %} +{% block content %}
diff --git a/src/templates/header.html b/src/templates/header.html index 00d3b00..021228a 100644 --- a/src/templates/header.html +++ b/src/templates/header.html @@ -5,22 +5,22 @@ - + - + - + @@ -52,13 +52,14 @@ href="{{ url_for('static', filename='css/head.css') }}" /> - + + - {{ title }} + {{ var['title'] }} @@ -87,23 +88,23 @@
-
{% block content %}{% endblock %}
+
{% include var['template'] %}
diff --git a/src/templates/home.html b/src/templates/home.html index f0c9198..e7f692f 100644 --- a/src/templates/home.html +++ b/src/templates/home.html @@ -1,4 +1,4 @@ -{% extends "header.html" %} {% block content %} +{% block content %}
@@ -8,14 +8,13 @@
- + />
- {% from 'partials/chess.html' import chess %} - {{ chess('asimonson1125') }} + {% from 'partials/chess.html' import chess %} {{ chess('asimonson1125') + }}
diff --git a/src/templates/projects.html b/src/templates/projects.html index 0d4ab1d..03456a4 100644 --- a/src/templates/projects.html +++ b/src/templates/projects.html @@ -1,4 +1,4 @@ -{% extends "header.html" %} {% block content %} +{% block content %}

Projects

@@ -37,8 +37,8 @@
{% from 'partials/project.html' import project %} - {% for i in projects %} - {{ project(i, projects[i]["classes"], projects[i]["status"], projects[i]["bgi"], projects[i]["content"], projects[i]["links"]) }} + {% for i in var["projects"] %} + {{ project(i, var["projects"][i]["classes"], var["projects"][i]["status"], var["projects"][i]["bgi"], var["projects"][i]["content"], var["projects"][i]["links"]) }} {% endfor %}