diff options
author | romangraef <roman.graef@gmail.com> | 2018-05-31 08:24:02 +0200 |
---|---|---|
committer | romangraef <roman.graef@gmail.com> | 2018-05-31 08:24:02 +0200 |
commit | 4a11fe9780deb76004be0e229edf298ac7200f0f (patch) | |
tree | 59d5d558f86483b4c73964b4683118cae87228dc | |
download | my-website-4a11fe9780deb76004be0e229edf298ac7200f0f.tar.gz my-website-4a11fe9780deb76004be0e229edf298ac7200f0f.tar.bz2 my-website-4a11fe9780deb76004be0e229edf298ac7200f0f.zip |
initial commit
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | app.py | 37 | ||||
-rw-r--r-- | json_serializable.py | 72 | ||||
-rw-r--r-- | static/.gallery.css.map | 7 | ||||
-rw-r--r-- | static/.gallery.scss | 28 | ||||
-rw-r--r-- | static/.reset.css.map | 7 | ||||
-rw-r--r-- | static/.reset.scss | 49 | ||||
-rw-r--r-- | static/.spoiler.css.map | 7 | ||||
-rw-r--r-- | static/.spoiler.scss | 21 | ||||
-rw-r--r-- | static/main.css.map | 7 | ||||
-rw-r--r-- | static/main.scss | 29 | ||||
-rw-r--r-- | templates/base.html | 19 | ||||
-rw-r--r-- | templates/index.html | 27 | ||||
-rw-r--r-- | templates/project.html | 6 |
14 files changed, 319 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3231b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +venv/ +*.css +projects.json @@ -0,0 +1,37 @@ +import json +from typing import List + +from flask import Flask, render_template, abort + +from json_serializable import JsonSerializable, from_json + +app = Flask(__name__) + + +class Project(JsonSerializable): + name: str + description: str + link: str + + +with open('projects.json') as handle: + project_data: List[Project] = from_json(json.load(handle), List[Project]) + + +@app.route('/projects/<project_name>') +def projects(project_name): + matches = [project for project in project_data if project.name.lower() == project_name.lower()] + if len(matches) == 0: + abort(404) + if len(matches) > 1: + abort(500) + return render_template('project.html', project=matches[0]) + + +@app.route('/') +def hello_world(): + return render_template('index.html') + + +if __name__ == '__main__': + app.run() diff --git a/json_serializable.py b/json_serializable.py new file mode 100644 index 0000000..87db9d1 --- /dev/null +++ b/json_serializable.py @@ -0,0 +1,72 @@ +import json +from datetime import datetime +from enum import Enum +from typing import Dict, Type, List + + +def from_json(data, cls: Type): + if issubclass(cls, List): + list_type: Type = cls.__args__[0] if hasattr(cls, '__args__') else type(data[0]) + instance = list() + for value in data: + instance.append(from_json(value, list_type)) + return instance + if issubclass(cls, Dict): + item = data.copy().popitem() if len(data) > 0 else None + key_type: Type = cls.__args__[0] if hasattr(cls, '__args__') else type(item[0]) + value_type: Type = cls.__args__[1] if hasattr(cls, '__args__') else type(item[0]) + instance = dict() + for key, value in data.items(): + instance[from_json(key, key_type)] = from_json(value, value_type) + return instance + if issubclass(cls, Enum): + return getattr(cls, data) + if issubclass(cls, datetime): + return datetime.fromtimestamp(data) + if issubclass(cls, JsonSerializable): + instance = cls() + annotations: dict = cls.__annotations__ if hasattr(cls, '__annotations__') else {} + for key, value in data.items(): + value_type = annotations[key] if key in annotations.keys() else type(value) + setattr(instance, key, from_json(value, value_type)) + return instance + return data + + +def prepare_json(obj): + if isinstance(obj, JsonSerializable): + return prepare_json(obj.__dict__) + if isinstance(obj, Enum): + return obj.name + if isinstance(obj, datetime): + return obj.timestamp() + if any(isinstance(obj, cls) for cls in [list, set, frozenset]): + return [prepare_json(data) for data in obj] + if isinstance(obj, dict): + return {key: prepare_json(value) for key, value in obj.items()} + return obj + + +class JsonSerializable(object): + @classmethod + def load(cls, data): + if isinstance(data, str): + data = json.loads(data) + return from_json(data, cls) + + @classmethod + def load_from_file(cls, filename): + filename = str(filename) + with open(filename) as handle: + return cls.load(handle.read()) + + def dump_to_file(self, filename): + filename = str(filename) + with open(filename, 'w') as handle: + handle.write(self.dump()) + + def dump(self): + return json.dumps(prepare_json(self)) + + def __repr__(self): + return self.dump() diff --git a/static/.gallery.css.map b/static/.gallery.css.map new file mode 100644 index 0000000..5c9be46 --- /dev/null +++ b/static/.gallery.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,QAAS;EACP,OAAO,EAAE,IAAI;;AAGf,gBAAiB;EACf,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,GAAG;EACX,MAAM,EAAE,cAAc", +"sources": [".gallery.scss"], +"names": [], +"file": ".gallery.css" +}
\ No newline at end of file diff --git a/static/.gallery.scss b/static/.gallery.scss new file mode 100644 index 0000000..20391a3 --- /dev/null +++ b/static/.gallery.scss @@ -0,0 +1,28 @@ +.gallery { + display: flex; +} + +.gallery-element { + background: #e6ebf6; + cursor: pointer; + display: block; + min-width: 200px; + padding: 10px; + width: 33%; + min-height: 200px; + margin: 5px; + border: gray 1px solid; +} + +.gallery-element:hover { + -webkit-transform: scale(1.2); + -moz-transform: scale(1.2); + -ms-transform: scale(1.2); + -o-transform: scale(1.2); + transform: scale(1.2); + -webkit-transition: all 100ms; + -moz-transition: all 100ms; + -ms-transition: all 100ms; + -o-transition: all 100ms; + transition: all 100ms; +} diff --git a/static/.reset.css.map b/static/.reset.css.map new file mode 100644 index 0000000..ae18cb8 --- /dev/null +++ b/static/.reset.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA;;;;;;;;;;;;wBAYyB;EACvB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,IAAI,EAAE,OAAO;EACb,cAAc,EAAE,QAAQ;;AAG1B,iDAAiD;AACjD;0CAC2C;EACzC,OAAO,EAAE,KAAK;;AAGhB,IAAK;EACH,WAAW,EAAE,CAAC;;AAGhB,MAAO;EACL,UAAU,EAAE,IAAI;;AAGlB,aAAc;EACZ,MAAM,EAAE,IAAI;;AAGd;iBACkB;EAChB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,IAAI;;AAGf,KAAM;EACJ,eAAe,EAAE,QAAQ;EACzB,cAAc,EAAE,CAAC", +"sources": [".reset.scss"], +"names": [], +"file": ".reset.css" +}
\ No newline at end of file diff --git a/static/.reset.scss b/static/.reset.scss new file mode 100644 index 0000000..2cd953d --- /dev/null +++ b/static/.reset.scss @@ -0,0 +1,49 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/static/.spoiler.css.map b/static/.spoiler.css.map new file mode 100644 index 0000000..10e1998 --- /dev/null +++ b/static/.spoiler.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAEA,cAAe;EACb,OAAO,EAAE,aAAa;EACtB,kBAAkB,EAAE,WAAW;EAC/B,eAAe,EAAE,WAAW;EAC5B,cAAc,EAAE,WAAW;EAC3B,aAAa,EAAE,WAAW;EAC1B,UAAU,EAAE,WAAW;EACvB,KAAK,EATM,OAAO;;AAapB,oBAAqB;EACnB,KAAK,EAbM,KAAK;;AAgBlB,QAAS;EACP,UAAU,EAlBC,OAAO;EAmBlB,KAAK,EAlBM,KAAK", +"sources": [".spoiler.scss"], +"names": [], +"file": ".spoiler.css" +}
\ No newline at end of file diff --git a/static/.spoiler.scss b/static/.spoiler.scss new file mode 100644 index 0000000..7cdf4c8 --- /dev/null +++ b/static/.spoiler.scss @@ -0,0 +1,21 @@ +$spoiler-bg: #aa1d68; +$spoiler-fg: white; +.spoiler:after { + content: attr(content); + -webkit-transition: color 500ms; + -moz-transition: color 500ms; + -ms-transition: color 500ms; + -o-transition: color 500ms; + transition: color 500ms; + color: $spoiler-bg; + +} + +.spoiler:hover:after { + color: $spoiler-fg; +} + +.spoiler { + background: $spoiler-bg; + color: $spoiler-fg; +} diff --git a/static/main.css.map b/static/main.css.map new file mode 100644 index 0000000..e30bd6e --- /dev/null +++ b/static/main.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAEA,cAAe;EACb,OAAO,EAAE,aAAa;EACtB,kBAAkB,EAAE,WAAW;EAC/B,eAAe,EAAE,WAAW;EAC5B,cAAc,EAAE,WAAW;EAC3B,aAAa,EAAE,WAAW;EAC1B,UAAU,EAAE,WAAW;EACvB,KAAK,EATM,OAAO;;AAapB,oBAAqB;EACnB,KAAK,EAbM,KAAK;;AAgBlB,QAAS;EACP,UAAU,EAlBC,OAAO;EAmBlB,KAAK,EAlBM,KAAK;;ACDlB;;;;;;;;;;;;wBAYyB;EACvB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,IAAI,EAAE,OAAO;EACb,cAAc,EAAE,QAAQ;;AAG1B,iDAAiD;AACjD;0CAC2C;EACzC,OAAO,EAAE,KAAK;;AAGhB,IAAK;EACH,WAAW,EAAE,CAAC;;AAGhB,MAAO;EACL,UAAU,EAAE,IAAI;;AAGlB,aAAc;EACZ,MAAM,EAAE,IAAI;;AAGd;iBACkB;EAChB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,IAAI;;AAGf,KAAM;EACJ,eAAe,EAAE,QAAQ;EACzB,cAAc,EAAE,CAAC;;AC/CnB,QAAS;EACP,OAAO,EAAE,IAAI;;AAGf,gBAAiB;EACf,UAAU,EAAE,OAAO;EACnB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,KAAK;EAChB,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,GAAG;EACV,UAAU,EAAE,KAAK;EACjB,MAAM,EAAE,GAAG;EACX,MAAM,EAAE,cAAc;;AAGxB,sBAAuB;EACrB,iBAAiB,EAAE,UAAU;EAC7B,cAAc,EAAE,UAAU;EAC1B,aAAa,EAAE,UAAU;EACzB,YAAY,EAAE,UAAU;EACxB,SAAS,EAAE,UAAU;EACrB,kBAAkB,EAAE,SAAS;EAC7B,eAAe,EAAE,SAAS;EAC1B,cAAc,EAAE,SAAS;EACzB,aAAa,EAAE,SAAS;EACxB,UAAU,EAAE,SAAS;;ACtBvB,CAAE;EACA,WAAW,EAAE,mCAAmC;;AAGlD,QAAS;EACP,OAAO,EAAE,IAAI;EACb,UAAU,EAAE,MAAM;EAClB,MAAM,EAAE,MAAM;EACd,KAAK,EAAE,GAAG;EACV,SAAS,EAAE,KAAK;;AAGlB,EAAG;EACD,SAAS,EAAE,GAAG;EACd,MAAM,EAAE,GAAG;;AAGb,OAAQ;EACN,MAAM,EAAE,IAAI;;AAGd,CAAE;EACA,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,OAAO", +"sources": [".spoiler.scss",".reset.scss",".gallery.scss","main.scss"], +"names": [], +"file": "main.css" +}
\ No newline at end of file diff --git a/static/main.scss b/static/main.scss new file mode 100644 index 0000000..93c71e3 --- /dev/null +++ b/static/main.scss @@ -0,0 +1,29 @@ +@import ".spoiler"; +@import ".reset"; +@import ".gallery"; + +* { + font-family: 'Montserrat', sans-serif !important; +} + +.content { + padding: 30px; + text-align: center; + margin: 0 auto; + width: 50%; + min-width: 600px; +} + +h1 { + font-size: 2em; + margin: 5px; +} + +.spacer { + height: 50px; +} + +a { + color: inherit; + text-decoration: inherit; +}
\ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..8d51f29 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,19 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" + content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> + <meta http-equiv="X-UA-Compatible" content="ie=edge"> + <title>{% block title %}{{ title }}{% endblock %}</title> + <link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet"> + <link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}"> +</head> +<body> +<div id="content" class="content"> + {% block body %} + No content found. THIS IS AN ERROR + {% endblock %} +</div> +</body> +</html>
\ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..cefce37 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{% block body %} + <h1>Hey, You!</h1> + <p>I am Roman Gräf</p> + <p>I am a programmer!</p> + <p>I do things for you!</p> + <p>As long as it is not webdesign, I will program nearly anything for you</p> + <div class="spacer"></div> + <h1>Projects</h1> + <div class="gallery"> + <a href="{{ url_for("projects", project_name="website") }}"> + <div class="gallery-element"> + This website + </div> + </a> + <div class="gallery-element"> + Discord Bots + </div> + <div class="gallery-element"> + LOGL + </div> + </div> + +{% endblock %} +{% block title %} + Roman Gräf +{% endblock %}
\ No newline at end of file diff --git a/templates/project.html b/templates/project.html new file mode 100644 index 0000000..076e0a2 --- /dev/null +++ b/templates/project.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% block body %} + <h1>{{ project.name }}</h1> + <p>{{ project.description }}</p> + <p><a href="{{ project.link }}">Link</a></p> +{% endblock %} |