elukjanovica 2024-04-28 14:59:03 +03:00
parent 15f824e2b7
commit eb7729c4d4
8 changed files with 263 additions and 48 deletions

2
TODO
View File

@ -1,7 +1,7 @@
[x] Attēlot lapu ar pamatinformāciju par izvēlēto spēli. [5] [x] Attēlot lapu ar pamatinformāciju par izvēlēto spēli. [5]
[x] Izveidotajā projektā jābūt direktorijam, kurā ir teksta faili ar spēļu atjauninājumu vēsturi (to varat izdomāt). Vienā no lapām ir jāparāda virsraksti, kas atbilst failu nosaukumiem, un saites uz attiecīgajiem rakstiem (teksta faila saturs). Katram rakstam ir jāatrodas savā lapā ar unikālu URL. Gan rakstu URL adreses, gan rakstu saraksts ir jāģenerē automātiski atbilstoši iepriekš minētā direktorija saturam. [30] [x] Izveidotajā projektā jābūt direktorijam, kurā ir teksta faili ar spēļu atjauninājumu vēsturi (to varat izdomāt). Vienā no lapām ir jāparāda virsraksti, kas atbilst failu nosaukumiem, un saites uz attiecīgajiem rakstiem (teksta faila saturs). Katram rakstam ir jāatrodas savā lapā ar unikālu URL. Gan rakstu URL adreses, gan rakstu saraksts ir jāģenerē automātiski atbilstoši iepriekš minētā direktorija saturam. [30]
[ ] Jāpievieno iespēja lietotājam lejupielādēt .pdf failu, kurā aprakstītas problēmas, ar kurām viņi saskārās jūsu spēlē. Lejupielādētais fails ir jāsaglabā īpaši norādītā direktorijā. [15] [ ] Jāpievieno iespēja lietotājam lejupielādēt .pdf failu, kurā aprakstītas problēmas, ar kurām viņi saskārās jūsu spēlē. Lejupielādētais fails ir jāsaglabā īpaši norādītā direktorijā. [15]
[ ] Jāizveido lapa, no kuras varat lejupielādēt jaunāko spēles versiju. [15] [x] Jāizveido lapa, no kuras varat lejupielādēt jaunāko spēles versiju. [15]
[ ] Piešķirot vērtējumu, tiks ņemts vērā arī tīmekļa aplikācijas vizuālais noformējums. Bootstrap bibliotēkas izmantošana ne tikai vienkāršos procesu, bet arī sniegs priekšrocības, ja tā tiks pareizi integrēta lietojumprogrammā. [20] [ ] Piešķirot vērtējumu, tiks ņemts vērā arī tīmekļa aplikācijas vizuālais noformējums. Bootstrap bibliotēkas izmantošana ne tikai vienkāršos procesu, bet arī sniegs priekšrocības, ja tā tiks pareizi integrēta lietojumprogrammā. [20]
[ ] Ir nepieciešams izveidot prezentāciju, demonstrēt visu paveikto darbu un demonstrēt izveidoto aplikāciju. [15] [ ] Ir nepieciešams izveidot prezentāciju, demonstrēt visu paveikto darbu un demonstrēt izveidoto aplikāciju. [15]
[ ] Visas pievienotās papildu funkcijas, kas uzlabo lietojumprogrammas lietošanas pieredzi un palielina tās tehnisko sarežģītību, var iegūt papildu punktus atkarībā no ieviešanas sarežģītības. [?] [ ] Visas pievienotās papildu funkcijas, kas uzlabo lietojumprogrammas lietošanas pieredzi un palielina tās tehnisko sarežģītību, var iegūt papildu punktus atkarībā no ieviešanas sarežģītības. [?]

Binary file not shown.

190
main.py
View File

@ -1,4 +1,4 @@
from flask import Flask, render_template, redirect, request, session, url_for from flask import Flask, render_template, redirect, request, session, url_for, g
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin, AdminIndexView, expose, BaseView from flask_admin import Admin, AdminIndexView, expose, BaseView
from flask_admin.contrib.sqla import ModelView from flask_admin.contrib.sqla import ModelView
@ -23,6 +23,30 @@ class Post(db.Model):
alias = db.Column(db.String(100), unique=True, nullable=False) alias = db.Column(db.String(100), unique=True, nullable=False)
title = db.Column(db.String(100), nullable=False) title = db.Column(db.String(100), nullable=False)
image = db.Column(db.String(100), nullable=False) image = db.Column(db.String(100), nullable=False)
class ForumCategory(db.Model):
id = db.Column(db.Integer, primary_key=True)
category_name = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(200))
class ForumPost(db.Model):
id = db.Column(db.Integer, primary_key=True)
category_id = db.Column(db.Integer, db.ForeignKey('forum_category.id'), nullable=False)
post_name = db.Column(db.String(100), nullable=False)
created_by = db.Column(db.String(100), nullable=False)
creation_date = db.Column(db.DateTime, nullable=False)
media = db.Column(db.String(100))
text = db.Column(db.Text, nullable=False)
edited = db.Column(db.Boolean, default=False)
class ForumComment(db.Model):
id = db.Column(db.Integer, primary_key=True)
post_id = db.Column(db.Integer, db.ForeignKey('forum_post.id'), nullable=False)
created_by = db.Column(db.String(100), nullable=False)
creation_date = db.Column(db.DateTime, nullable=False)
media = db.Column(db.String(100))
text = db.Column(db.Text, nullable=False)
edited = db.Column(db.Boolean, default=False)
def admin_login_required(view_func): def admin_login_required(view_func):
@wraps(view_func) @wraps(view_func)
@ -41,12 +65,10 @@ class MyAdminIndexView(AdminIndexView):
class UserAdminView(ModelView): class UserAdminView(ModelView):
column_exclude_list = ['password'] column_exclude_list = ['password']
form_excluded_columns = ['password'] form_excluded_columns = ['password']
can_export = True
export_types = ['csv']
class PostAdminView(ModelView): class PostAdminView(ModelView):
can_edit = True
can_delete = True
create_modal = True
edit_modal = True
can_export = True can_export = True
export_types = ['csv'] export_types = ['csv']
@ -70,6 +92,13 @@ def check_admin_login():
ADMIN_USERNAME = 'user' ADMIN_USERNAME = 'user'
ADMIN_PASSWORD = '1234321' ADMIN_PASSWORD = '1234321'
@app.before_request
def before_request():
g.user = None
if 'username' in session:
user = User.query.filter_by(username=session['username']).first()
g.user = user
@app.route("/admin/login", methods=["GET", "POST"]) @app.route("/admin/login", methods=["GET", "POST"])
def admin_login(): def admin_login():
if request.method == "POST": if request.method == "POST":
@ -87,44 +116,6 @@ def admin_logout():
session.pop("admin_logged_in", None) session.pop("admin_logged_in", None)
return redirect(url_for("admin_login")) return redirect(url_for("admin_login"))
@app.route("/")
def index():
latest_posts = Post.query.all()
return render_template("index.html", latest_posts=latest_posts)
@app.route("/posts")
def all_posts():
all_posts = Post.query.all()
return render_template("posts.html", posts=all_posts)
@app.route("/about")
def about():
return render_template("about.html")
@app.route("/posts/<alias>")
def post(alias):
post_info = Post.query.filter_by(alias=alias).first()
if post_info:
return render_template(f"{alias}.html", post_info=post_info)
else:
return "Post not found", 404
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
user = User.query.filter_by(username=username, password=password).first()
if user:
session["username"] = username
return redirect(url_for("index"))
return render_template("auth/login.html")
@app.route("/logout")
def logout():
session.pop("username", None)
return redirect(url_for("index"))
@app.route("/register", methods=["GET", "POST"]) @app.route("/register", methods=["GET", "POST"])
def register(): def register():
if request.method == "POST": if request.method == "POST":
@ -142,12 +133,123 @@ def register():
error_msg = "Username already exists" error_msg = "Username already exists"
return render_template("auth/register.html", error_msg=error_msg) return render_template("auth/register.html", error_msg=error_msg)
new_user = User(username=username, email=email, password=password) new_user = User(username=username, email=email, password=password) # type: ignore
db.session.add(new_user) db.session.add(new_user)
db.session.commit() db.session.commit()
return redirect(url_for("login")) return redirect(url_for("login"))
return render_template("auth/register.html") return render_template("auth/register.html")
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
user = User.query.filter_by(username=username, password=password).first()
if user:
session["username"] = username
return redirect(url_for("index"))
return render_template("auth/login.html")
@app.route("/logout")
def logout():
session.pop("username", None)
return redirect(url_for("index"))
@app.route("/")
def index():
latest_posts = Post.query.all()[::-1]
return render_template("index.html", latest_posts=latest_posts)
@app.route("/posts")
def all_posts():
all_posts = Post.query.all()[::-1]
return render_template("posts.html", posts=all_posts)
@app.route("/posts/<alias>")
def post(alias):
post_info = Post.query.filter_by(alias=alias).first()
if post_info:
return render_template(f"{alias}.html", post_info=post_info)
else:
return "Post not found", 404
@app.route('/forums')
def forums():
categories = ForumCategory.query.all()
posts = ForumPost.query.all()
comments = ForumComment.query.all()
return render_template('forums.html', categories=categories, posts=posts, comments=comments)
@app.route('/forums/<int:category_id>')
def category(category_id):
category = ForumCategory.query.get_or_404(category_id)
posts = ForumPost.query.filter_by(category_id=category_id).all()
return render_template('category.html', category=category, posts=posts)
@app.route('/forums/<int:post_id>')
def new_post(post_id):
post = ForumPost.query.get_or_404(post_id)
comments = ForumComment.query.filter_by(post_id=post_id).all()
return render_template('post.html', post=post, comments=comments)
@app.route('/forums/create_post', methods=['GET', 'POST'])
def create_post():
if request.method == 'POST':
category_id = request.form['category_id']
post_name = request.form['post_name']
created_by = request.form['created_by']
text = request.form['text']
new_post = ForumPost(category_id=category_id, post_name=post_name, created_by=created_by, text=text) # type: ignore
db.session.add(new_post)
db.session.commit()
return redirect(url_for('forums'))
else:
categories = ForumCategory.query.all()
return render_template('create_post.html', categories=categories)
@app.route('/forums/create_comment', methods=['POST']) # type: ignore
def create_comment():
if request.method == 'POST':
post_id = request.form['post_id']
created_by = request.form['created_by']
text = request.form['text']
new_comment = ForumComment(post_id=post_id, created_by=created_by, text=text) # type: ignore
db.session.add(new_comment)
db.session.commit()
return redirect(url_for('post', post_id=post_id))
@app.route('/forums/upvote_post/<int:post_id>')
def upvote_post(post_id):
post = ForumPost.query.get_or_404(post_id)
post.upvotes += 1
db.session.commit()
return redirect(url_for('post', post_id=post_id))
@app.route('/forums/downvote_post/<int:post_id>')
def downvote_post(post_id):
post = ForumPost.query.get_or_404(post_id)
post.downvotes += 1
db.session.commit()
return redirect(url_for('post', post_id=post_id))
@app.route('/forums/upvote_comment/<int:comment_id>')
def upvote_comment(comment_id):
comment = ForumComment.query.get_or_404(comment_id)
comment.upvotes += 1
db.session.commit()
return redirect(url_for('post', post_id=comment.post_id))
@app.route('/forums/downvote_comment/<int:comment_id>')
def downvote_comment(comment_id):
comment = ForumComment.query.get_or_404(comment_id)
comment.downvotes += 1
db.session.commit()
return redirect(url_for('post', post_id=comment.post_id))
@app.route("/about")
def about():
return render_template("about.html")
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True) app.run(debug=True)

View File

@ -434,6 +434,56 @@ i.far.fa-comment {
text-align: center; text-align: center;
} }
/* Forums */
.forum-card {
margin-bottom: 20px;
}
.forum-media {
max-width: 100%;
height: auto;
}
.upvote-btn,
.downvote-btn {
cursor: pointer;
font-size: 1.2rem;
color: #6c757d;
}
.upvote-btn:hover,
.downvote-btn:hover {
color: #007bff;
}
.vote-count {
font-size: 1rem;
font-weight: bold;
}
.comment-section {
margin-top: 20px;
}
.comment {
margin-bottom: 10px;
}
.comment-media {
max-width: 100%;
height: auto;
}
.comment-text {
margin-bottom: 5px;
}
.comment-details {
font-size: 0.8rem;
color: #6c757d;
}
/* Mobile-specific */ /* Mobile-specific */
@media only screen and (max-width: 767px) { @media only screen and (max-width: 767px) {
/* Navbar */ /* Navbar */

View File

@ -37,7 +37,13 @@
</div> </div>
</li> </li>
<li class="dropdown pull-left"> <li class="dropdown pull-left">
<a href="#" class="dropbtn">Account</a> <a href="#" class="dropbtn">
{% if g.user %}
{{ g.user.username }}
{% else %}
Account
{% endif %}
</a>
<div class="dropdown-content"> <div class="dropdown-content">
{% if g.user %} {% if g.user %}
<a href="{{ url_for('logout') }}">Log Out</a> <a href="{{ url_for('logout') }}">Log Out</a>
@ -63,4 +69,4 @@
</footer> </footer>
<script src="{{ url_for('static', filename='js/main.js') }}"></script> <script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,26 @@
{% extends 'base.html' %}
{% block title %}{{ category.category_name }} Category{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>{{ category.category_name }}</h1>
<div class="card mt-4">
<div class="card-body">
<div class="list-group">
{% for post in posts %}
<a href="{{ url_for('new_post', post_id=post.id) }}" class="list-group-item list-group-item-action">
<h5 class="mb-1">{{ post.post_name }}</h5>
<p class="mb-1">{{ post.text }}</p>
<small>Created by {{ post.created_by }} - {{ post.creation_date }}</small>
</a>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'base.html' %}
{% block title %}Forums{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>Welcome to the Forums!</h1>
{% for category in categories %}
<div class="card mt-4">
<div class="card-header">{{ category.category_name }}</div>
<div class="card-body">
<div class="list-group">
{% for post in posts %}
{% if post.category_id == category.id %}
<a href="{{ url_for('new_post', post_id=post.id) }}" class="list-group-item list-group-item-action">
<h5 class="mb-1">{{ post.post_name }}</h5>
<p class="mb-1">{{ post.text }}</p>
<small>Created by {{ post.created_by }} - {{ post.creation_date }}</small>
</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

View File

@ -10,7 +10,7 @@
{% block content %} {% block content %}
<section class="simple-text"> <section class="simple-text">
<p>Welcome to 'Picture Puzzle remake' website! Here you can see all game updates, articles, and more. If you want to download the latest version of game, just ask that bird on top :)</p></br> <p>Welcome to 'Picture Puzzle remake' website! Here you can see all game updates, articles, and more. If you want to download the latest version of game, just click on that bird on top <i class="fa-solid fa-feather"></i></p></br>
</section> </section>
<section class="featured-posts"> <section class="featured-posts">