added functionality to submit entries

This commit is contained in:
InigoAllende
2026-01-19 17:23:11 +01:00
parent 435d7c826c
commit 5ccdcabe8b
7 changed files with 163 additions and 18 deletions

View File

@@ -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

View File

@@ -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])

View File

@@ -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

View File

@@ -237,3 +237,7 @@ textarea {
}
}
}
p.error {
color: #f65994;
}

4
templates/error.html Normal file
View File

@@ -0,0 +1,4 @@
<main>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
</main>

View File

@@ -20,8 +20,29 @@
}
</style>
<main>
<div class="panel padded">
{% comment %}
{% if submission_success %}
<div class="panel padded">
<h2>Thank you for your submission!</h2>
<p>Your entry has been received, voting will start on <strong>?????</strong> 📅</p>
</div>
{% endif %}
<div class="panel padded" style="margin-top: 20px;">
<!-- During the submission period -->
{% if user %}
{% if submission_success %}
<p>You can submit multiple entries until <strong>?????</strong> 📅</p>
{% else %}
<p>Submit your game for the Godot showreel until <strong>?????</strong> 📅</p>
{% endif %}
<a class="button primary" href="/submit">Submit entry</a>
{% else %}
You need to be logged in to submit an entry:
<a href="/login" class="button dim small">Log In</a>
{% endif %}
</div>
<div class="panel padded" style="margin-top: 20px;">
<!-- During the voting period -->
{% if user %}
{% if user.can_vote() %}
@@ -52,21 +73,20 @@
You need to be logged in to vote:
<a href="/login" class="button dim small">Log In</a>
{% endif %}
{% endcomment %}
<h1>Welcome!</h1>
<p>The voting period for this years showreel videos has finished.</p>
<p style="margin: 20px 0;">Thank you to everyone who participated!</p>
</div>
<div class="panel padded" style="margin-top: 20px;">
<h2>Previous editions:<span><a href="https://www.youtube.com/playlist?list=PLeG_dAglpVo6EpaO9A1nkwJZOwrfiLdQ8">(View all)</a></span></h2>
<div class="grid-2" style="margin-top: 10px;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/n1Lon_Q2T18" frameborder="0" allowfullscreen="" style="width:100%;aspect-ratio:16/9;height:auto; border-radius: 11px;"></iframe>
<iframe width="560" height="315" src="https://www.youtube.com/embed/W1_zKxYEP6Q" frameborder="0" allowfullscreen="" style="width:100%;aspect-ratio:16/9;height:auto; border-radius: 11px;"></iframe>
<h1>Welcome!</h1>
<p>The voting period for this years showreel videos has finished.</p>
<p style="margin: 20px 0;">Thank you to everyone who participated!</p>
</div>
<div class="panel padded" style="margin-top: 20px;">
<h2>Previous editions:<span><a href="https://www.youtube.com/playlist?list=PLeG_dAglpVo6EpaO9A1nkwJZOwrfiLdQ8">(View all)</a></span></h2>
<div class="grid-2" style="margin-top: 10px;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/n1Lon_Q2T18" frameborder="0" allowfullscreen="" style="width:100%;aspect-ratio:16/9;height:auto; border-radius: 11px;"></iframe>
<iframe width="560" height="315" src="https://www.youtube.com/embed/W1_zKxYEP6Q" frameborder="0" allowfullscreen="" style="width:100%;aspect-ratio:16/9;height:auto; border-radius: 11px;"></iframe>
</div>
</div>
</div>
</main>

54
templates/submit.html Normal file
View File

@@ -0,0 +1,54 @@
<main id="submission-form">
<div>
<h1>Showreel Submission</h1>
<p>Fill in the form to submit your video for the Godot Showreel.</p>
</div>
<hr>
<form method="POST" enctype="multipart/form-data" hx-post="{{ url_for("votes.post_submit", _method='POST') }}" hx-target='#submission-form' hx-swap='outerHTML'>
{{ form.csrf_token }}
{{ form.game.label }}<br>
{{ form.game(size=100) }}<br>
{% for error in form.game.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.author_name.label }}<br>
{{ form.author_name(size=100) }}<br>
{% for error in form.author_name.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.contact_email.label }}<br>
{{ form.contact_email(size=100) }}<br>
{% for error in form.contact_email.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.video_link.label }}<br>
{{ form.video_link(size=100) }}<br>
{% for error in form.video_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.video_download_link.label }}<br>
{{ form.video_download_link(size=100) }}<br>
{% for error in form.video_download_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.follow_me_link.label }}<br>
{{ form.follow_me_link(size=100) }}<br>
{% for error in form.follow_me_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.store_link.label }}<br>
{{ form.store_link(size=100) }}<br>
{% for error in form.store_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
<button type="submit" class="button secondary">Submit</button>
</form>
</main>