mirror of
https://github.com/godotengine/godot-showreel-voting.git
synced 2026-09-03 18:15:13 +03:00
added functionality to submit entries
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -237,3 +237,7 @@ textarea {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.error {
|
||||
color: #f65994;
|
||||
}
|
||||
4
templates/error.html
Normal file
4
templates/error.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<main>
|
||||
<h1>{{ title }}</h1>
|
||||
<p>{{ message }}</p>
|
||||
</main>
|
||||
@@ -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
54
templates/submit.html
Normal 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>
|
||||
Reference in New Issue
Block a user