simulate Single Page App with websockets

This commit is contained in:
2023-01-29 18:04:16 -06:00
parent f99ad56e1d
commit 8b4a97bf73
11 changed files with 105 additions and 57 deletions

View File

@@ -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)

Binary file not shown.

View File

@@ -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)}}

View File

@@ -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);
});

View File

@@ -1,4 +1,4 @@
{% extends "header.html" %} {% block content %}
{% block content %}
<div class="foreground">
<div class="col">
<div id="aboutMe" data-aos="fade-up">
@@ -41,10 +41,10 @@
<div id="skills" data-aos="fade-up">
<h2>Skills</h2>
{% 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", ]) }}
</Skills>
<div class="chess">
@@ -121,8 +121,8 @@
</div>
<div class="timeline checkbox-client">
{% 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 %}
</div>
<script>toggle('up')</script>

View File

@@ -1,4 +1,4 @@
{% extends "header.html" %} {% block content %}
{% block content %}
<div class="fPage">
<div class="heightBox">
<div class="neonBox">

View File

@@ -5,22 +5,22 @@
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="{{ description }}" />
<meta name="description" content="{{ var['description'] }}" />
<meta property="og:title" content="Andrew Simonson" />
<meta name="og:description" content="{{ description }}" />
<meta name="og:description" content="{{ var['description'] }}" />
<meta property="og:type" content="website" />
<meta
property="og:image"
content="{{ url_for('static', filename='photos/sun.png') }}"
content="https://asimonson.com{{ url_for('static', filename='photos/sun.png') }}"
/>
<meta property="og:url" content="https://asimonson.com" />
<meta property="twitter:title" content="Andrew Simonson" />
<meta name="twitter:description" content="{{ description }}" />
<meta name="twitter:description" content="{{ var['description'] }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:site_name" content="Andrew Simonson - Portfolio" />
<meta
property="twitter:image"
content="{{ url_for('static', filename='photos/sun.png') }}"
content="https://asimonson.com{{ url_for('static', filename='photos/sun.png') }}"
/>
<meta name="twitter:image:alt" content="some example picture idk" />
<meta name="twitter:site" content="@asimonson1125" />
@@ -52,13 +52,14 @@
href="{{ url_for('static', filename='css/head.css') }}"
/>
<link rel="canonical" href="https://asimonson.com/{{ canonical }}" />
<link rel="canonical" href="https://asimonson.com/{{ var['canonical'] }}" />
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js" integrity="sha512-eVL5Lb9al9FzgR63gDs1MxcDS2wFu3loYAgjIH0+Hg38tCS8Ag62dwKyH+wzDb+QauDpEZjXbMn11blw8cbTJQ==" crossorigin="anonymous"></script>
<script src="{{ url_for('static', filename='js/idler.js') }}"></script>
<script src="{{ url_for('static', filename='js/checkbox.js') }}"></script>
<script src="{{ url_for('static', filename='js/responsive.js') }}"></script>
<script src="{{ url_for('static', filename='js/chessbed.js') }}"></script>
<title>{{ title }}</title>
<title>{{ var['title'] }}</title>
</head>
<body>
@@ -87,23 +88,23 @@
<div class="navControl">
<div class="navBar">
<div class="navElement">
<a href="/">Home</a>
<p onclick="emitData('goto', 'home')">Home</p>
</div>
<div class="navElement">
<a href="Resume.pdf" target="_blank"> Resume </a>
</div>
<div class="navElement">
<a href="/projects">Projects</a>
<p onclick="emitData('goto', 'projects')">Projects</p>
</div>
<!-- <a href="/activities">Activities</a> -->
<div class="navElement">
<a href="/about">About Me</a>
<p onclick="emitData('goto', 'about')">About Me</p>
</div>
</div>
</div>
</div>
</div>
<div id="root">{% block content %}{% endblock %}</div>
<div id="root">{% include var['template'] %}</div>
<div class="footer">
{% include 'partials/socials.html' %}
</div>

View File

@@ -1,4 +1,4 @@
{% extends "header.html" %} {% block content %}
{% block content %}
<div class="homeground">
<div class="relative">
<div class="flex">
@@ -8,14 +8,13 @@
</div>
</div>
<div class="onRight" data-aos="fade-up">
<iframe
title="langstats"
<img
src="{{ url_for('static', filename='readme-stats-vercel-01-25-2023.svg') }}"
class="langstats"
></iframe>
/>
<div class="chess">
{% from 'partials/chess.html' import chess %}
{{ chess('asimonson1125') }}
{% from 'partials/chess.html' import chess %} {{ chess('asimonson1125')
}}
</div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
{% extends "header.html" %} {% block content %}
{% block content %}
<div class="foreground">
<div data-aos="fade-up">
<h2 class="concentratedHead">Projects</h2>
@@ -37,8 +37,8 @@
</div>
<div class="projectList centeredForeground checkbox-client">
{% 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 %}
</div>
</div>