diff --git a/TODO b/TODO index 7b71015..910d50d 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ [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] [ ] 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] [ ] 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. [?] \ No newline at end of file diff --git a/instance/Picture_Puzzle_web.db b/instance/Picture_Puzzle_web.db index 8961cc1..fee7441 100644 Binary files a/instance/Picture_Puzzle_web.db and b/instance/Picture_Puzzle_web.db differ diff --git a/main.py b/main.py index a1e1815..01ff867 100644 --- a/main.py +++ b/main.py @@ -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_admin import Admin, AdminIndexView, expose, BaseView 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) title = 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): @wraps(view_func) @@ -41,12 +65,10 @@ class MyAdminIndexView(AdminIndexView): class UserAdminView(ModelView): column_exclude_list = ['password'] form_excluded_columns = ['password'] + can_export = True + export_types = ['csv'] class PostAdminView(ModelView): - can_edit = True - can_delete = True - create_modal = True - edit_modal = True can_export = True export_types = ['csv'] @@ -70,6 +92,13 @@ def check_admin_login(): ADMIN_USERNAME = 'user' 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"]) def admin_login(): if request.method == "POST": @@ -87,44 +116,6 @@ def admin_logout(): session.pop("admin_logged_in", None) 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/") -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"]) def register(): if request.method == "POST": @@ -142,12 +133,123 @@ def register(): error_msg = "Username already exists" 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.commit() return redirect(url_for("login")) 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/") +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/') +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/') +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/') +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/') +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/') +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/') +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__': app.run(debug=True) \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index 262dafa..c9656ed 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -434,6 +434,56 @@ i.far.fa-comment { 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 */ @media only screen and (max-width: 767px) { /* Navbar */ diff --git a/templates/base.html b/templates/base.html index fff1e4e..0495710 100644 --- a/templates/base.html +++ b/templates/base.html @@ -37,7 +37,13 @@