Done for now

This commit is contained in:
2022-07-05 22:40:53 +02:00
parent 4b404f8569
commit 1f7e70247f
10 changed files with 81 additions and 7673 deletions

17
.idea/dataSources.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="db" uuid="84671ca6-a908-465f-865b-9dfeff8695f7">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.34.0/sqlite-jdbc-3.34.0.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

View File

@@ -0,0 +1,17 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ourVersions">
<value>
<list size="2">
<item index="0" class="java.lang.String" itemvalue="3.10" />
<item index="1" class="java.lang.String" itemvalue="3.11" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="TsLint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@@ -1,12 +1,15 @@
# Portfolio Website
A quick portfolio website made to run on Heroku without any storage bucket.
A quickly made portfolio website made to run on Heroku without any storage bucket.
Make sure the following environment variables are set:
- `DATABASE_URL`
- `PASSWORD`
- `SECRET_KEY`
Tables can be created with:
```python
>>> from app import db, app
>>> db.create_all(app=app)
```shell
$ python app.py
```
## Missing features

57
app.py
View File

@@ -1,6 +1,15 @@
import os
from flask import Flask, render_template, jsonify, abort, send_file, request, redirect, flash
from flask import (
Flask,
render_template,
jsonify,
abort,
send_file,
request,
redirect,
flash,
)
from sqlalchemy import func
from base64 import standard_b64decode, standard_b64encode
from io import BytesIO
@@ -8,7 +17,7 @@ from io import BytesIO
from model import db, Post, Category, ImageBase64
# Check for environment variable
env_vars = ["DATABASE_URL", "PASSWORD", 'SECRET_KEY']
env_vars = ["DATABASE_URL", "PASSWORD", "SECRET_KEY"]
for env_var in env_vars:
if not os.getenv(env_var):
@@ -16,10 +25,10 @@ for env_var in env_vars:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL")
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JSON_SORT_KEYS'] = False
app.secret_key = os.getenv('SECRET_KEY')
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("DATABASE_URL")
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["JSON_SORT_KEYS"] = False
app.secret_key = os.getenv("SECRET_KEY")
# Bind db to application
db.init_app(app)
@@ -28,14 +37,16 @@ db.init_app(app)
@app.route("/")
def index():
posts = Post.get_posts()
print(posts[0].title)
# print(posts[0].title)
return render_template("main/index.html", posts=posts)
@app.route('/<string:category_name>')
@app.route("/<string:category_name>")
def category(category_name):
category_item = Category.query.filter(func.lower(Category.name) == category_name.replace('_', ' ')).first()
category_item = Category.query.filter(
func.lower(Category.name) == category_name.replace("_", " ")
).first()
if not category_item:
return abort(404)
@@ -45,12 +56,12 @@ def category(category_name):
return render_template("main/index.html", posts=posts)
@app.route('/contact')
@app.route("/contact")
def contact():
return render_template("main/contact.html")
@app.route("/api/post/<int:post_id>", methods=["POST"])
@app.route("/api/post/<int:post_id>")
def get_post(post_id):
post = Post.query.get(post_id)
@@ -60,7 +71,7 @@ def get_post(post_id):
return jsonify({"success": False})
@app.route('/images/<string:filename>')
@app.route("/images/<string:filename>")
def get_image(filename):
image_b64 = ImageBase64.query.filter(ImageBase64.filename == filename).first()
@@ -69,36 +80,40 @@ def get_image(filename):
image = standard_b64decode(image_b64.data)
return send_file(BytesIO(image), mimetype=image_b64.mimetype, attachment_filename=filename)
return send_file(
BytesIO(image), mimetype=image_b64.mimetype, attachment_filename=filename
)
@app.route('/adm/uploadfile', methods=['POST', 'GET'])
@app.route("/adm/uploadfile", methods=["POST", "GET"])
def file_uploaded():
if request.method == 'POST':
if not request.form.get('password') == os.getenv('PASSWORD'):
if request.method == "POST":
if not request.form.get("password") == os.getenv("PASSWORD"):
flash("Wrong Password")
return redirect("/adm/uploadfile")
# check if the post request has the file part
if 'files' not in request.files:
if "files" not in request.files:
return redirect("/adm/uploadfile")
files = request.files.getlist('files')
files = request.files.getlist("files")
# if user does not select file, browser also
# submit an empty part without filename
for file in files:
if file.filename == '':
if file.filename == "":
flash("No files")
return redirect("/adm/uploadfile")
data = standard_b64encode(file.read()).decode()
database_object = ImageBase64(filename=file.filename, mimetype=file.mimetype, data=data)
database_object = ImageBase64(
filename=file.filename, mimetype=file.mimetype, data=data
)
db.session.add(database_object)
db.session.commit()
return render_template("adm/uploadfile.html")
if __name__ == '__main__':
if __name__ == "__main__":
app.app_context().push()
db.create_all()

7594
static/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,40 +0,0 @@
/*
* Start of Custom CSS
*/
.nav-link, .navbar-brand {
font-family: 'Amatic SC', cursive;
font-size: 40px; }
.card-img-overlay {
opacity: 0; }
.card:hover .card-img-overlay {
opacity: 1; }
.card {
margin: 10px; }
.card .card-img-overlay {
padding: 0; }
.card .card-img-overlay .card-title-bg {
height: 25%;
opacity: 0.8; }
.card .card-img-overlay .card-title-bg .card-text {
opacity: 1; }
a .card, a .card:hover {
color: inherit; }
.modal-body img {
margin: 10px; }
.social-icon {
margin: 10px; }
body {
padding-top: 6.5rem; }
footer {
margin-top: 10px;
margin-bottom: 20px; }
/*# sourceMappingURL=style.css.map */

View File

@@ -5,12 +5,9 @@ $('#detailModal').on('show.bs.modal', function (event) {
" <span class=\"sr-only\">Loading...</span>\n" +
"</div>");
$('#details-description').html('');
$.post(`/api/post/${post_id}`, data => {
$.get(`/api/post/${post_id}`, data => {
let post = data.post;
console.log(post);
// $('#details-title').text(post.title);
$('#details-intro').html(post.intro);
$('#details-description').html(post.description);
});

View File

@@ -8,7 +8,7 @@
<link href="https://fonts.googleapis.com/css?family=Amatic+SC" rel="stylesheet">
<!-- Bootstrap first, then custom style -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/bootstrap.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css"
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr"
crossorigin="anonymous">

View File

@@ -1,5 +1,5 @@
<nav class="navbar navbar-expand-md navbar-light bg-light fixed-top">
<a class="navbar-brand font-weight-bold" href="{{ url_for("index") }}">Marlous</a>
<a class="navbar-brand font-weight-bold" href="{{ url_for("index") }}">Marijn</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
@@ -8,7 +8,7 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{% set items = [("Nice Title", 'internal_title'),] %}
{% set items = [("Category", ''),] %}
{% for item in items %}
<li class="nav-item">
<a class="nav-link {% if item[1] == request.path[1:] %}active{% endif %}"