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 1246f6b..5e1ed2b 100644 Binary files a/src/requirements.txt and b/src/requirements.txt differ diff --git a/src/static/css/head.css b/src/static/css/head.css index 17ee26a..a77ad06 100644 --- a/src/static/css/head.css +++ b/src/static/css/head.css @@ -1 +1 @@ -.line:not(:first-child){position:absolute;top:0;left:0}.line:nth-child(1){animation:clip 6000ms -600ms linear infinite,glitch1 2500ms -433ms linear infinite}@keyframes glitch1{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-1px);color:#4E9A26}98%{transform:translateX(4px);color:#AC1212}99%{transform:translateX(-1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(2){animation:clip 6000ms -1200ms linear infinite,glitch2 2500ms -234ms linear infinite}@keyframes glitch2{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-2px);color:#4E9A26}98%{transform:translateX(-1px);color:#AC1212}99%{transform:translateX(5px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(3){animation:clip 6000ms -1800ms linear infinite,glitch3 2500ms -189ms linear infinite}@keyframes glitch3{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-4px);color:#4E9A26}98%{transform:translateX(2px);color:#AC1212}99%{transform:translateX(-2px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(4){animation:clip 6000ms -2400ms linear infinite,glitch4 2500ms -105ms linear infinite}@keyframes glitch4{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-3px);color:#4E9A26}98%{transform:translateX(4px);color:#AC1212}99%{transform:translateX(1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(5){animation:clip 6000ms -3000ms linear infinite,glitch5 2500ms -89ms linear infinite}@keyframes glitch5{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-2px);color:#4E9A26}98%{transform:translateX(-2px);color:#AC1212}99%{transform:translateX(3px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(6){animation:clip 6000ms -3600ms linear infinite,glitch6 2500ms -936ms linear infinite}@keyframes glitch6{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(3px);color:#4E9A26}98%{transform:translateX(-4px);color:#AC1212}99%{transform:translateX(0px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(7){animation:clip 6000ms -4200ms linear infinite,glitch7 2500ms -594ms linear infinite}@keyframes glitch7{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(1px);color:#4E9A26}98%{transform:translateX(5px);color:#AC1212}99%{transform:translateX(-3px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(8){animation:clip 6000ms -4800ms linear infinite,glitch8 2500ms -464ms linear infinite}@keyframes glitch8{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-2px);color:#4E9A26}98%{transform:translateX(5px);color:#AC1212}99%{transform:translateX(1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(9){animation:clip 6000ms -5400ms linear infinite,glitch9 2500ms -520ms linear infinite}@keyframes glitch9{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(3px);color:#4E9A26}98%{transform:translateX(-2px);color:#AC1212}99%{transform:translateX(3px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(10){animation:clip 6000ms -6000ms linear infinite,glitch10 2500ms -463ms linear infinite}@keyframes glitch10{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(1px);color:#4E9A26}98%{transform:translateX(1px);color:#AC1212}99%{transform:translateX(-3px);color:#fff}100%{transform:translateX(0)}}@keyframes clip{0%{clip-path:polygon(0 100%, 100% 100%, 100% 120%, 0 120%)}100%{clip-path:polygon(0 -20%, 100% -20%, 100% 0%, 0 0)}} +.line:not(:first-child){position:absolute;top:0;left:0}.line:nth-child(1){animation:clip 6000ms -600ms linear infinite,glitch1 2500ms -540ms linear infinite}@keyframes glitch1{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(3px);color:#4E9A26}98%{transform:translateX(-3px);color:#AC1212}99%{transform:translateX(-3px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(2){animation:clip 6000ms -1200ms linear infinite,glitch2 2500ms -210ms linear infinite}@keyframes glitch2{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(1px);color:#4E9A26}98%{transform:translateX(-2px);color:#AC1212}99%{transform:translateX(-1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(3){animation:clip 6000ms -1800ms linear infinite,glitch3 2500ms -866ms linear infinite}@keyframes glitch3{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(2px);color:#4E9A26}98%{transform:translateX(0px);color:#AC1212}99%{transform:translateX(4px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(4){animation:clip 6000ms -2400ms linear infinite,glitch4 2500ms -60ms linear infinite}@keyframes glitch4{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-3px);color:#4E9A26}98%{transform:translateX(1px);color:#AC1212}99%{transform:translateX(1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(5){animation:clip 6000ms -3000ms linear infinite,glitch5 2500ms -221ms linear infinite}@keyframes glitch5{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(0px);color:#4E9A26}98%{transform:translateX(-3px);color:#AC1212}99%{transform:translateX(-4px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(6){animation:clip 6000ms -3600ms linear infinite,glitch6 2500ms -716ms linear infinite}@keyframes glitch6{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(1px);color:#4E9A26}98%{transform:translateX(5px);color:#AC1212}99%{transform:translateX(-1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(7){animation:clip 6000ms -4200ms linear infinite,glitch7 2500ms -157ms linear infinite}@keyframes glitch7{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(-1px);color:#4E9A26}98%{transform:translateX(-3px);color:#AC1212}99%{transform:translateX(-2px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(8){animation:clip 6000ms -4800ms linear infinite,glitch8 2500ms -955ms linear infinite}@keyframes glitch8{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(1px);color:#4E9A26}98%{transform:translateX(1px);color:#AC1212}99%{transform:translateX(-4px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(9){animation:clip 6000ms -5400ms linear infinite,glitch9 2500ms -54ms linear infinite}@keyframes glitch9{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(0px);color:#4E9A26}98%{transform:translateX(-3px);color:#AC1212}99%{transform:translateX(-1px);color:#fff}100%{transform:translateX(0)}}.line:nth-child(10){animation:clip 6000ms -6000ms linear infinite,glitch10 2500ms -857ms linear infinite}@keyframes glitch10{0%{transform:translateX(0)}96%{transform:translateX(0);color:#fff}97%{transform:translateX(3px);color:#4E9A26}98%{transform:translateX(1px);color:#AC1212}99%{transform:translateX(2px);color:#fff}100%{transform:translateX(0)}}@keyframes clip{0%{clip-path:polygon(0 100%, 100% 100%, 100% 120%, 0 120%)}100%{clip-path:polygon(0 -20%, 100% -20%, 100% 0%, 0 0)}} diff --git a/src/static/js/responsive.js b/src/static/js/responsive.js index 2bbd958..934d7b5 100644 --- a/src/static/js/responsive.js +++ b/src/static/js/responsive.js @@ -87,3 +87,26 @@ function toggleMenu() { } } } + +let socket = io(); + +function emit(event) { + socket.emit(event); +} + +function emitData(event, data) { + socket.emit(event, data) +} + +socket.on('goto', (page) => { + 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 %}