add support for multiple store links

This commit is contained in:
InigoAllende
2026-08-10 17:03:39 +02:00
parent aaeb31521d
commit 984c44fc90
6 changed files with 147 additions and 11 deletions

View File

@@ -26,6 +26,15 @@ def validate_urls(form, field):
raise ValidationError(f'Invalid URL: {field.data}')
def validate_store_urls(form, field):
# Form is submitted with format: "url1;url2;url3"
if field.data:
urls = field.data.split(';')
for url in urls:
parsed = urlparse(url)
if not all([parsed.scheme, parsed.netloc]):
raise ValidationError(f'Invalid URL: {url}')
class CastVoteForm(FlaskForm):
action = StringField('Action', validators=[validate_action])
video_id = IntegerField('Video ID', validators=[InputRequired()])
@@ -42,7 +51,7 @@ class VideoSubmissionForm(FlaskForm):
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])
store_link = StringField('Store Link', validators=[InputRequired(), validate_store_urls])
class ManageShowreelsForm(FlaskForm):

View File

@@ -206,7 +206,7 @@ def download_vote_results():
video.video_link,
video.video_download_link,
video.contact_email,
video.store_link,
'\n'.join(video.store_link.split(';')),
extract_steam_app_id(video.store_link),
plus_votes,
minus_votes,
@@ -237,7 +237,6 @@ def submit():
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)
@@ -246,7 +245,20 @@ def submit():
@bp.route('/submit', methods=['POST'])
@auth.login_required
def post_submit():
form = VideoSubmissionForm()
formdata = request.form.copy()
links = [
formdata.get("store_link", "").strip(),
formdata.get("store_link_2", "").strip(),
formdata.get("store_link_3", "").strip(),
formdata.get("store_link_4", "").strip(),
formdata.get("store_link_5", "").strip(),
]
formdata["store_link"] = ";".join(link for link in links if link)
form = VideoSubmissionForm(formdata)
if not form.validate():
return render_template('submit.html', user=g.user, form=form)
@@ -356,7 +368,18 @@ def update_submission(video_id: int):
if video.showreel.status != ShowreelStatus.OPENED_TO_SUBMISSIONS:
return render_template('error.html', title="Cannot Update Submission", message="Submissions can only be updated while the showreel is open to submissions.")
form = VideoSubmissionForm()
formdata = request.form.copy()
links = [
formdata.get("store_link", "").strip(),
formdata.get("store_link_2", "").strip(),
formdata.get("store_link_3", "").strip(),
formdata.get("store_link_4", "").strip(),
formdata.get("store_link_5", "").strip(),
]
formdata["store_link"] = ";".join(link for link in links if link)
form = VideoSubmissionForm(formdata, obj=video)
if not form.validate():
return render_template('update-submissions.html', user=g.user, submissions=[video], open_showreel=video.showreel, form=form)

View File

@@ -50,7 +50,16 @@
{% endfor %}<br>
{{ form.store_link.label }}<br>
<p class="info">We will use this to promote your game in future events and showcase pages.</p>
{{ form.store_link(size=100) }}<br>
<div id="store-link-extra-container">
{% for i in range(2, 6) %}
<div class="store-link-extra" id="store-link-{{ i }}-container" style="display: none;">
<label for="store-link-{{ i }}">Additional Store Link {{ i }}</label><br>
<input type="url" id="store-link-{{ i }}" name="store_link_{{ i }}" size="100"><br>
</div>
{% endfor %}
</div>
{% for error in form.store_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
@@ -98,4 +107,40 @@
previewContainer.style.display = 'block';
});
})
</script>
<script>
// Handle multiple store links
const storeLinks = [
document.getElementById("store_link"),
document.getElementById("store-link-2"),
document.getElementById("store-link-3"),
document.getElementById("store-link-4"),
document.getElementById("store-link-5")
];
function updateStoreLinkVisibility() {
for (let i = 1; i < storeLinks.length; i++) {
const container = document.getElementById(`store-link-${i + 1}-container`);
container.style.display = storeLinks[i - 1].value.trim() ? "block" : "none";
}
}
storeLinks.forEach(link => {
link.addEventListener("input", updateStoreLinkVisibility);
});
// populate form fields with existing links
document.addEventListener('DOMContentLoaded', function() {
const existingLinks = {{ form.store_link.data|tojson }}.split(';');
for (let i = 0; i < existingLinks.length && i < storeLinks.length; i++) {
storeLinks[i].value = existingLinks[i];
const container = document.getElementById(`store-link-${i + 2}-container`);
container.style.display = storeLinks[i].value.trim() ? "block" : "none";
}
updateStoreLinkVisibility();
});
</script>

View File

@@ -4,7 +4,7 @@
<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 id="submission-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>
@@ -49,9 +49,18 @@
<p class="error">{{ error }}</p>
{% endfor %}<br>
{{ form.store_link.label }}
{{ form.store_link.label }}<br>
<p class="info">We will use this to promote your game in future events and showcase pages.</p>
{{ form.store_link(size=100) }}<br>
<div id="store-link-extra-container">
{% for i in range(2, 6) %}
<div class="store-link-extra" id="store-link-{{ i }}-container" style="display: none;">
<label for="store-link-{{ i }}">Additional Store Link {{ i }}</label><br>
<input type="url" id="store-link-{{ i }}" name="store_link_{{ i }}" size="100"><br>
</div>
{% endfor %}
</div>
{% for error in form.store_link.errors %}
<p class="error">{{ error }}</p>
{% endfor %}<br>
@@ -100,4 +109,28 @@
previewContainer.style.display = 'block';
});
})
</script>
<script>
// Handle multiple store links
const storeLinks = [
document.getElementById("store_link"),
document.getElementById("store-link-2"),
document.getElementById("store-link-3"),
document.getElementById("store-link-4"),
document.getElementById("store-link-5")
];
function updateStoreLinkVisibility() {
for (let i = 1; i < storeLinks.length; i++) {
const container = document.getElementById(`store-link-${i + 1}-container`);
container.style.display = storeLinks[i - 1].value.trim() ? "block" : "none";
}
}
storeLinks.forEach(link => {
link.addEventListener("input", updateStoreLinkVisibility);
});
updateStoreLinkVisibility();
</script>

View File

@@ -105,11 +105,24 @@
<h2>Submission info:</h2>
<div class="col-2">
<p class="truncate" title="{{ data.game }}">Project: <strong>{{ data.game }}</strong></p>
<p>Video Link: <a href="{{ data.video_link }}" target="_blank">{{ data.video_link }}</a></p>
<p>Author: <strong>{{ data.author }}</strong></p>
<p>Store Link: <a href="{{ data.store_link }}" target="_blank">{{ data.store_link }}</a></p>
<p>Category: <strong>{{ data.category }}</strong></p>
<p>Follow them: <a href="{{ data.follow_me_link }}" target="_blank">{{ data.follow_me_link }}</a></p>
<p>Video Link: <a href="{{ data.video_link }}" target="_blank">{{ data.video_link }}</a></p>
<div>
<p>Store Links</p>
{% set store_links = data.store_link.split(';') %}
<ul>
{% for link in store_links %}
{% if link %}
<li>
<a href="{{ link }}" target="_blank">{{ link }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
</div>

View File

@@ -136,11 +136,24 @@
<h2>Submission info:</h2>
<div class="col-2">
<p class="truncate" title="{{ data.game }}">Project: <strong>{{ data.game }}</strong></p>
<p>Video Link: <a href="{{ data.video_link }}" target="_blank">{{ data.video_link }}</a></p>
<p>Author: <strong>{{ data.author }}</strong></p>
<p>Store Link: <a href="{{ data.store_link }}" target="_blank">{{ data.store_link }}</a></p>
<p>Category: <strong>{{ data.category }}</strong></p>
<p>Video Link: <a href="{{ data.video_link }}" target="_blank">{{ data.video_link }}</a></p>
<p>Follow them: <a href="{{ data.follow_me_link }}" target="_blank">{{ data.follow_me_link }}</a></p>
<div>
<p>Store Links</p>
{% set store_links = data.store_link.split(';') %}
<ul>
{% for link in store_links %}
{% if link %}
<li>
<a href="{{ link }}" target="_blank">{{ link }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
</div>