mirror of
https://github.com/tiyn/container-critique.git
synced 2025-04-01 23:57:49 +02:00
src: added user page
This commit is contained in:
parent
f4f8e3eb7f
commit
ceadc87e16
@ -12,7 +12,7 @@ The blog is intended to be used to review and critique things.
|
||||
- [x] Login
|
||||
- [x] Logout
|
||||
- [x] Register
|
||||
- [ ] User Page
|
||||
- [x] User Page
|
||||
- [ ] Review blog entries
|
||||
- [x] Writing entries
|
||||
- [ ] Editing entries
|
||||
|
13
src/app.py
13
src/app.py
@ -45,10 +45,19 @@ def index():
|
||||
@app.route("/archive")
|
||||
@app.route("/archive.html")
|
||||
def archive():
|
||||
entries = db.get_entries()
|
||||
content = con_gen.gen_arch_string()
|
||||
return render_template("archive.html", content_string=content)
|
||||
|
||||
|
||||
@app.route("/user/<name>")
|
||||
def user(name):
|
||||
content = con_gen.gen_user_string(name)
|
||||
if content != "":
|
||||
return render_template("user.html", name=name, content_string=content)
|
||||
abort(404)
|
||||
|
||||
|
||||
@app.route("/entry/<ident>")
|
||||
def entry(ident):
|
||||
content = con_gen.gen_stand_string(ident)
|
||||
@ -103,12 +112,10 @@ def logout():
|
||||
@app.route("/register", methods=["GET", "POST"])
|
||||
@app.route("/register.html", methods=["GET", "POST"])
|
||||
def register():
|
||||
if current_user.is_authenticated or not REGISTER:
|
||||
if current_user.is_authenticated or not config.ALLOW_REGISTRATION:
|
||||
return redirect(url_for("index"))
|
||||
form = RegisterForm()
|
||||
if form.validate_on_submit():
|
||||
if not config.ALLOW_REGISTRATION:
|
||||
return redirect(url_for("index"))
|
||||
db_user = db.get_user_by_name(form.username.data)
|
||||
if db_user is None:
|
||||
user = User(form.username.data)
|
||||
|
@ -33,6 +33,8 @@ def gen_arch_string():
|
||||
entries = db.get_entries()
|
||||
if entries is None:
|
||||
return ""
|
||||
entries.sort(key=lambda y: y[1])
|
||||
entries.reverse()
|
||||
entries.sort(key=lambda y: y[2])
|
||||
entries.reverse()
|
||||
for entry in entries:
|
||||
@ -40,6 +42,7 @@ def gen_arch_string():
|
||||
title = entry[1]
|
||||
year = entry[2]
|
||||
rating = entry[4]
|
||||
username = db.get_user_by_id(entry[5])[1]
|
||||
if year != last_year:
|
||||
if last_year != "":
|
||||
content_string += "</ul>\n"
|
||||
@ -47,18 +50,55 @@ def gen_arch_string():
|
||||
content_string += "<ul>\n"
|
||||
last_year = year
|
||||
content_string += "<li>"
|
||||
content_string += "[<a href=\"" + \
|
||||
url_for("index", _anchor=str(ident)) + "\">link</a> - <a href=\"" \
|
||||
+ url_for("entry", ident=str(ident)) + "\">standalone</a>] "
|
||||
content_string += title + " " + rating_to_star(rating)
|
||||
content_string += "<br></li>\n"
|
||||
content_string += title + "<a href=\"" + \
|
||||
url_for("entry", ident=str(ident)) + "\"> " + \
|
||||
rating_to_star(rating) + " by " + username
|
||||
content_string += "</a><br></li>\n"
|
||||
|
||||
return content_string
|
||||
|
||||
|
||||
def gen_user_string(name):
|
||||
"""
|
||||
Creates and returns a archive string of every file in ENTRY_DIR.
|
||||
|
||||
Returns:
|
||||
string: html-formatted archive-string.
|
||||
"""
|
||||
content_string = ""
|
||||
last_year = ""
|
||||
entries = db.get_entries_by_name(name)
|
||||
if entries is None:
|
||||
return ""
|
||||
entries.sort(key=lambda y: y[1])
|
||||
entries.reverse()
|
||||
entries.sort(key=lambda y: y[2])
|
||||
entries.reverse()
|
||||
for entry in entries:
|
||||
ident = entry[0]
|
||||
title = entry[1]
|
||||
year = entry[2]
|
||||
rating = entry[4]
|
||||
username = db.get_user_by_id(entry[5])[1]
|
||||
if year != last_year:
|
||||
if last_year != "":
|
||||
content_string += "</ul>\n"
|
||||
content_string += "<h2>" + year + "</h2>\n"
|
||||
content_string += "<ul>\n"
|
||||
last_year = year
|
||||
content_string += "<li>"
|
||||
content_string += title + "<a href=\"" + \
|
||||
url_for("entry", ident=str(ident)) + "\"> " + \
|
||||
rating_to_star(rating)
|
||||
content_string += "</a><br></li>\n"
|
||||
|
||||
return content_string
|
||||
|
||||
|
||||
def gen_index_string():
|
||||
"""
|
||||
Create and returns a string including every file in the database as an index.
|
||||
Create and returns a string including every file in the database as an
|
||||
index.
|
||||
|
||||
Returns:
|
||||
string: html-formatted index string.
|
||||
@ -77,12 +117,12 @@ def gen_index_string():
|
||||
username = db.get_user_by_id(entry[5])[1]
|
||||
reviewed = entry[6]
|
||||
content_string += "<div class=\"entry\">\n"
|
||||
content_string += "<h1 id=\"" + str(ident) + "\">" + title + \
|
||||
" (" + year + ") " + rating_to_star(rating) + "</h1>\n"
|
||||
content_string += "[<a href=\"" + url_for("entry", ident=str(ident)) + \
|
||||
"\">" + "standalone" + "</a>]<br>\n"
|
||||
content_string += "<small>rated " + str(rating) + " by " + username + \
|
||||
" on " + str(reviewed) + "</small><br>"
|
||||
content_string += "<h1 id=\"" + str(ident) + "\"><a href=\"" + \
|
||||
url_for("entry", ident=str(ident)) + "\">" + title + \
|
||||
" (" + year + ") " + rating_to_star(rating) + "</a></h1>\n"
|
||||
content_string += "<small>rated " + str(rating) + \
|
||||
"/100 by <a href=\"" + url_for("user", name=username) + "\">" \
|
||||
+ username + "</a> on " + str(reviewed) + "</small><br>"
|
||||
content_string += text
|
||||
content_string += "<br>"
|
||||
content_string += "</div>"
|
||||
@ -113,10 +153,11 @@ def gen_stand_string(ident):
|
||||
" (" + year + ") "
|
||||
content_string += rating_to_star(rating)
|
||||
content_string += "</h1>\n"
|
||||
content_string += "[<a href=\"" + url_for("index", ident=str(ident)) + \
|
||||
"\">" + "link" + "</a>]<br>\n"
|
||||
content_string += "<small>rated " + str(rating) + " by " + \
|
||||
username + " on " + str(reviewed) + "</small><br>\n"
|
||||
content_string += "<small>rated " + str(rating) + \
|
||||
"/100 by <a href=\"" + url_for("user", name=username) + "\">" + \
|
||||
username + "</a> on <a href=\"" + \
|
||||
url_for("index", _anchor=str(ident)) + "\">" + str(reviewed) + \
|
||||
"</a></small><br>\n"
|
||||
content_string += text + "<br>\n"
|
||||
return content_string
|
||||
|
||||
@ -143,7 +184,7 @@ def get_rss_string():
|
||||
reviewed = entry[6]
|
||||
content_string += "<item>\n"
|
||||
content_string += "<title>" + title + "(" + year + ") " + \
|
||||
rating_to_star(rating) + "</title>\n"
|
||||
rating_to_star(rating) + " by " + username + "</title>\n"
|
||||
content_string += "<guid>" + \
|
||||
url_for("index", _anchor=str(ident), _external=True) + \
|
||||
"</guid>\n"
|
||||
|
@ -97,6 +97,15 @@ class Database:
|
||||
crs.execute(query)
|
||||
return crs.fetchall()
|
||||
|
||||
def get_entries_by_name(self, name):
|
||||
db = self.connect()
|
||||
crs = db.cursor()
|
||||
query = "SELECT * FROM " + self.ENTRY_TABLE_FILE + \
|
||||
" WHERE user_id = (SELECT id FROM " + self.USER_TABLE_FILE + \
|
||||
" WHERE name = ?)"
|
||||
crs.execute(query, (name, ))
|
||||
return crs.fetchall()
|
||||
|
||||
def check_user_name(self, name):
|
||||
if self.get_user_by_name(name) is None:
|
||||
return True
|
||||
|
22
src/forms.py
22
src/forms.py
@ -4,27 +4,33 @@ from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, PasswordField, SubmitField
|
||||
from wtforms.fields.html5 import IntegerField
|
||||
from wtforms.validators import DataRequired, EqualTo, InputRequired, \
|
||||
NumberRange, ValidationError
|
||||
NumberRange, ValidationError, Length
|
||||
|
||||
|
||||
class LoginForm(FlaskForm):
|
||||
username = StringField("Username", validators=[DataRequired()])
|
||||
password = PasswordField("Password", validators=[DataRequired()])
|
||||
username = StringField("Username", validators=[DataRequired(),
|
||||
Length(min=4, max=32)])
|
||||
password = PasswordField("Password", validators=[DataRequired(),
|
||||
Length(min=4, max=32)])
|
||||
submit = SubmitField("Sign In")
|
||||
|
||||
|
||||
class RegisterForm(FlaskForm):
|
||||
username = StringField("Username", validators=[DataRequired()])
|
||||
password = PasswordField("Password", validators=[DataRequired()])
|
||||
username = StringField("Username", validators=[DataRequired(),
|
||||
Length(min=4, max=32)])
|
||||
password = PasswordField("Password", validators=[DataRequired(),
|
||||
Length(min=4, max=32)])
|
||||
password2 = PasswordField(
|
||||
"Repeat Password", validators=[DataRequired(), EqualTo("password")])
|
||||
submit = SubmitField("Register")
|
||||
|
||||
|
||||
class WriteForm(FlaskForm):
|
||||
name = StringField("Name", validators=[DataRequired()])
|
||||
date = IntegerField("Release Year", default=date.today().year, validators=[DataRequired(
|
||||
), NumberRange(min=0, max=date.today().year, message="Year has to be valid.")])
|
||||
name = StringField("Name", validators=[DataRequired(),
|
||||
Length(min=2, max=64)])
|
||||
date = IntegerField("Release Year", default=date.today().year, validators=[
|
||||
DataRequired(), NumberRange(min=0, max=date.today().year,
|
||||
message="Year has to be valid.")])
|
||||
text = CKEditorField("Text", validators=[DataRequired()])
|
||||
rating = IntegerField("Rating", default=50, validators=[InputRequired(
|
||||
), NumberRange(min=0, max=100, message="Number has to be between 0 and 100.")])
|
||||
|
@ -2,82 +2,14 @@
|
||||
|
||||
:root {
|
||||
--bg0: rgb(29,32,33);
|
||||
--bg1: rgb(50,55,60);
|
||||
--color0: rgb(220,120,0);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(29,32,33);
|
||||
--footerbg0: rgb(50,55,60);
|
||||
--link0: rgb(220, 120, 0);
|
||||
--link1: rgb(255,255,255);
|
||||
--menulink0: rgb(220, 120, 0);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(29,32,33);
|
||||
--menubg0: rgb(50,55,60);
|
||||
--text0: rgb(235,219,178);
|
||||
--text1: rgb(220, 120, 0);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
:root {
|
||||
--bg0: rgb(255,255,255);
|
||||
--bg1: rgb(192,192,192);
|
||||
--color0: rgb(0,0,120);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(192,192,192);
|
||||
--link0: rgb(0,0,120);
|
||||
--link1: rgb(255,255,255);
|
||||
@ -13,71 +13,3 @@
|
||||
--text0: rgb(0,0,0);
|
||||
--text1: rgb(0,0,120);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
@ -9,15 +9,30 @@
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
text-decoration: none;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: var(--menulink0);
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu a:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -30,12 +45,22 @@ html {
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
height: 100px;
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer .center {
|
||||
text-align: center;
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
color: var(--text1);
|
||||
margin: 5px auto 2px auto;
|
||||
}
|
||||
|
||||
li:not(:last-child) {
|
||||
@ -52,43 +77,8 @@ ul {
|
||||
padding-left: 20;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
min-height: 100%;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 5%;
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
padding: 10px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
.important {
|
||||
font-size: xx-large;
|
||||
padding-left: 25vw;
|
||||
padding-right: 25vw;
|
||||
padding-top: 30vh;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.important span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 80px;
|
||||
padding-top: 10px;
|
||||
span {
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.main-menu-dropdown span {
|
||||
@ -103,6 +93,63 @@ ul {
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.important span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
min-height: 100%;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 5%;
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
padding: 10px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
background: var(--bg1);
|
||||
border-left: 10px solid var(--color0);
|
||||
border-radius: 0 10px 30px 0;
|
||||
color: var(--text0);
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
|
||||
.hide-menu:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
|
||||
.important {
|
||||
font-size: xx-large;
|
||||
padding-left: 25vw;
|
||||
padding-right: 25vw;
|
||||
padding-top: 30vh;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 80px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
float: right;
|
||||
font-family: monospace;
|
||||
@ -111,14 +158,9 @@ ul {
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
height: 100px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
@ -135,6 +177,11 @@ ul {
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
.main-menu a {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.hide-menu {
|
||||
position: absolute;
|
||||
right: 40px;
|
||||
@ -147,6 +194,7 @@ ul {
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
height: 100vh;
|
||||
line-height: normal;
|
||||
padding: 80px 0;
|
||||
@ -157,23 +205,8 @@ ul {
|
||||
transition: var(--transtime);
|
||||
width: 100%;
|
||||
}
|
||||
.main-menu a {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#main-menu-check:checked ~ .main-menu {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
border-radius: 0 10px 30px 0;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
margin: 5px auto 2px auto;
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="blogarchive">
|
||||
<h1>Archive</h1><br>
|
||||
<div class="archive">
|
||||
<h1>Archive</h1><br>
|
||||
{% autoescape off %}
|
||||
{{ content_string }}
|
||||
{% endautoescape %}
|
||||
|
@ -30,18 +30,16 @@
|
||||
{% endblock %}
|
||||
<!-- Content -->
|
||||
<footer>
|
||||
<div class="center">
|
||||
Made with <a href="https://github.com/tiyn/container-critique">Container Critique </a>.<br>
|
||||
{% if current_user.is_anonymous %}
|
||||
<a href="{{ url_for('login') }}">Login</a>
|
||||
-
|
||||
<a href="{{ url_for('register') }}">Register</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('logout') }}">Logout</a>
|
||||
-
|
||||
<a href="{{ url_for('write') }}">Write entry</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
Made with <a href="https://github.com/tiyn/container-critique">Container Critique </a>.<br>
|
||||
{% if current_user.is_anonymous %}
|
||||
<a href="{{ url_for('login') }}">Login</a>
|
||||
-
|
||||
<a href="{{ url_for('register') }}">Register</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('logout') }}">Logout</a>
|
||||
-
|
||||
<a href="{{ url_for('write') }}">Write entry</a>
|
||||
{% endif %}
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
12
src/templates/user.html
Normal file
12
src/templates/user.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "template.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="archive">
|
||||
<h1>User: {{ User }}</h1><br>
|
||||
{% autoescape off %}
|
||||
{{ content_string }}
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user