From 5ccdcabe8bfffd921fa32185f55d8c5a25ffc7a9 Mon Sep 17 00:00:00 2001 From: InigoAllende Date: Mon, 19 Jan 2026 17:23:11 +0100 Subject: [PATCH] added functionality to submit entries --- compose.yml | 2 ++ gdshowreelvote/blueprints/forms.py | 20 ++++++++++- gdshowreelvote/blueprints/votes.py | 47 ++++++++++++++++++++++++-- static/css/1.1/base.css | 4 +++ templates/error.html | 4 +++ templates/home.html | 50 ++++++++++++++++++--------- templates/submit.html | 54 ++++++++++++++++++++++++++++++ 7 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 templates/error.html create mode 100644 templates/submit.html diff --git a/compose.yml b/compose.yml index a6143eb..88aeebd 100644 --- a/compose.yml +++ b/compose.yml @@ -19,6 +19,8 @@ services: image: docker.io/mariadb volumes: - mariadb_data:/var/lib/mysql + ports: + - "3306:3306" environment: MARIADB_DATABASE: showreel MARIADB_USER: showreel diff --git a/gdshowreelvote/blueprints/forms.py b/gdshowreelvote/blueprints/forms.py index 3eb6804..b4f6b9f 100644 --- a/gdshowreelvote/blueprints/forms.py +++ b/gdshowreelvote/blueprints/forms.py @@ -1,5 +1,6 @@ +from urllib.parse import urlparse from flask_wtf import FlaskForm -from wtforms import IntegerField, StringField, ValidationError +from wtforms import IntegerField, StringField, ValidationError, EmailField from wtforms.validators import InputRequired from gdshowreelvote.utils import downvote_video, skip_video, upvote_video @@ -15,6 +16,13 @@ def validate_action(form, field): if field.data: if VOTE_ACTIONS.get(field.data) is None: raise ValidationError(f"Action '{field.data}' is not supported.") + + +def validate_urls(form, field): + if field.data: + parsed = urlparse(field.data) + if not all([parsed.scheme, parsed.netloc]): + raise ValidationError(f'Invalid URL: {field.data}') class CastVoteForm(FlaskForm): @@ -24,3 +32,13 @@ class CastVoteForm(FlaskForm): class SelectVideoForm(FlaskForm): video_id = IntegerField('Video ID', validators=[InputRequired()]) + + +class VideoSubmissionForm(FlaskForm): + game = StringField('Game Title', validators=[InputRequired()]) + author_name = StringField('Author Name', validators=[InputRequired()]) + contact_email = EmailField('Contact Email', validators=[InputRequired()]) + video_link = StringField('Video Link', validators=[InputRequired(), validate_urls]) # TODO: Check specific URL formats + video_download_link = StringField('Video Download Link', validators=[InputRequired(), validate_urls]) + follow_me_link = StringField('Follow Me Link', validators=[InputRequired(), validate_urls]) + store_link = StringField('Store Link', validators=[InputRequired(), validate_urls]) diff --git a/gdshowreelvote/blueprints/votes.py b/gdshowreelvote/blueprints/votes.py index c0d4c01..6a3f6c4 100644 --- a/gdshowreelvote/blueprints/votes.py +++ b/gdshowreelvote/blueprints/votes.py @@ -6,8 +6,8 @@ from werkzeug.exceptions import NotFound from flask import Blueprint, Response, current_app, g, redirect, render_template, request, url_for from gdshowreelvote import auth -from gdshowreelvote.blueprints.forms import VOTE_ACTIONS, CastVoteForm, SelectVideoForm -from gdshowreelvote.database import DB, User, Video, Vote +from gdshowreelvote.blueprints.forms import VOTE_ACTIONS, CastVoteForm, SelectVideoForm, VideoSubmissionForm +from gdshowreelvote.database import DB, Showreel, ShowreelStatus, User, Video, Vote from gdshowreelvote.utils import choose_random_video, get_total_votes, video_data, vote_data, voting_possible @@ -188,3 +188,46 @@ def video_view(video_id: int): data = video_data(video) content = render_template('video-view.html', data=data) return render_template('default.html', content = content, user=g.user, hide_nav=True) + + +@bp.route('/submit', methods=['GET']) +def submit(): + active_showreel = DB.session.query(Showreel).filter(Showreel.status == ShowreelStatus.OPENED_TO_SUBMISSIONS).count() + if not active_showreel == 1: + current_app.logger.warning("No active showreel or multiple active showreels found.") + error_template = render_template('error.html', title="Submissions Closed", message="Submissions are currently closed.") + return render_template('default.html', content = error_template, user=g.user) + + form = VideoSubmissionForm() + content = render_template('submit.html', user=g.user, form=form) + return render_template('default.html', content = content, user=g.user) + + +@bp.route('/submit', methods=['POST']) +@auth.login_required +def post_submit(): + form = VideoSubmissionForm() + if not form.validate(): + return render_template('submit.html', user=g.user, form=form) + + active_showreel = DB.session.query(Showreel).filter(Showreel.status == ShowreelStatus.OPENED_TO_SUBMISSIONS).all() + if not active_showreel or len(active_showreel) > 1: + current_app.logger.warning("No active showreel or multiple active showreels found.") + return render_template('error.html', title="Submissions Closed", message="Submissions are currently closed.") + + active_showreel = active_showreel[0] + new_video = Video( + game=form.game.data, + author_name=form.author_name.data, + contact_email=form.contact_email.data, + video_link=form.video_link.data, + video_download_link=form.video_download_link.data, + follow_me_link=form.follow_me_link.data, + store_link=form.store_link.data, + author=g.user, + showreel=active_showreel + ) + DB.session.add(new_video) + DB.session.commit() + + return render_template('home.html', user=g.user, submission_success=True) # TODO: Add flag to show submission success message diff --git a/static/css/1.1/base.css b/static/css/1.1/base.css index f76e325..8942d1a 100644 --- a/static/css/1.1/base.css +++ b/static/css/1.1/base.css @@ -237,3 +237,7 @@ textarea { } } } + +p.error { + color: #f65994; +} \ No newline at end of file diff --git a/templates/error.html b/templates/error.html new file mode 100644 index 0000000..1c55724 --- /dev/null +++ b/templates/error.html @@ -0,0 +1,4 @@ +
+

{{ title }}

+

{{ message }}

+
\ No newline at end of file diff --git a/templates/home.html b/templates/home.html index ff48ca4..b4791dd 100644 --- a/templates/home.html +++ b/templates/home.html @@ -20,8 +20,29 @@ }
-
- {% comment %} + {% if submission_success %} +
+

Thank you for your submission!

+

Your entry has been received, voting will start on ????? 📅

+
+ {% endif %} +
+ + {% if user %} + {% if submission_success %} +

You can submit multiple entries until ????? 📅

+ {% else %} +

Submit your game for the Godot showreel until ????? 📅

+ {% endif %} + Submit entry + {% else %} + You need to be logged in to submit an entry: + Log In + {% endif %} + +
+ +
{% if user %} {% if user.can_vote() %} @@ -52,21 +73,20 @@ You need to be logged in to vote: Log In {% endif %} - {% endcomment %} -

Welcome!

-

The voting period for this years showreel videos has finished.

-

Thank you to everyone who participated!

-
- - -
-

Previous editions:(View all)

-
- - +

Welcome!

+

The voting period for this years showreel videos has finished.

+

Thank you to everyone who participated!

+
+ + +
+

Previous editions:(View all)

+
+ + +
-
diff --git a/templates/submit.html b/templates/submit.html new file mode 100644 index 0000000..8bc1a6c --- /dev/null +++ b/templates/submit.html @@ -0,0 +1,54 @@ +
+
+

Showreel Submission

+

Fill in the form to submit your video for the Godot Showreel.

+
+
+
+ {{ form.csrf_token }} + + {{ form.game.label }}
+ {{ form.game(size=100) }}
+ {% for error in form.game.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.author_name.label }}
+ {{ form.author_name(size=100) }}
+ {% for error in form.author_name.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.contact_email.label }}
+ {{ form.contact_email(size=100) }}
+ {% for error in form.contact_email.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.video_link.label }}
+ {{ form.video_link(size=100) }}
+ {% for error in form.video_link.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.video_download_link.label }}
+ {{ form.video_download_link(size=100) }}
+ {% for error in form.video_download_link.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.follow_me_link.label }}
+ {{ form.follow_me_link(size=100) }}
+ {% for error in form.follow_me_link.errors %} +

{{ error }}

+ {% endfor %}
+ + {{ form.store_link.label }}
+ {{ form.store_link(size=100) }}
+ {% for error in form.store_link.errors %} +

{{ error }}

+ {% endfor %}
+ + +
+
\ No newline at end of file