news: add summary and thumbnails to topics

Provides data for homepage, as well as others topics
This commit is contained in:
Darks 2023-07-25 22:26:16 +02:00 committed by Eragon
parent c68b9b2048
commit af61b21fc8
Signed by: Eragon
GPG Key ID: 087126EBFC725006
10 changed files with 122 additions and 61 deletions

View File

@ -1,6 +1,6 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, MultipleFileField, SelectField
from wtforms.validators import InputRequired, Length
from wtforms import StringField, SubmitField, TextAreaField, MultipleFileField, SelectField, DecimalField
from wtforms.validators import InputRequired, Length, Optional
import app.utils.validators as vd
from app.utils.antibot_field import AntibotField
@ -54,6 +54,14 @@ class TopicCreationForm(CommentForm):
'Nom du sujet',
validators=[InputRequired(), Length(min=3, max=128)])
summary = TextAreaField(
'Résumé',
validators=[Optional(), Length(min=3, max=128)])
thumbnail = DecimalField(
'N° de lillustration',
validators=[Optional(), vd.attachment_exists])
submit = SubmitField('Créer le sujet')
@ -61,11 +69,7 @@ class AnonymousTopicCreationForm(TopicCreationForm, AnonymousCommentForm):
ab = AntibotField()
class TopicEditForm(CommentEditForm):
title = StringField(
'Nom du sujet',
validators=[InputRequired(), Length(min=3, max=128)])
class TopicEditForm(TopicCreationForm):
# List of forums is generated at runtime
forum = SelectField(
'Forum',

View File

@ -1,6 +1,7 @@
from app import db
from app.models.post import Post
from sqlalchemy.orm import backref
from sqlalchemy.dialects.postgresql import UUID
class Topic(Post):
__tablename__ = 'topic'
@ -29,10 +30,17 @@ class Topic(Post):
backref=backref('topics', lazy='dynamic'), foreign_keys=forum_id)
# Associated thread
thread_id = db.Column(db.Integer,db.ForeignKey('thread.id'),nullable=False)
thread_id = db.Column(db.Integer, db.ForeignKey('thread.id'), nullable=False)
thread = db.relationship('Thread', foreign_keys=thread_id,
back_populates='owner_topic')
# Summary
summary = db.Column(db.UnicodeText)
# ID of thumbnail
thumbnail_id = db.Column(UUID(as_uuid=True), db.ForeignKey('attachment.id'), nullable=True)
thumbnail = db.relationship('Attachment', foreign_keys=thumbnail_id, lazy='joined')
# Number of views in the forum
views = db.Column(db.Integer)

View File

@ -54,6 +54,7 @@ def forum_page(f, page=1):
db.session.merge(th)
t = Topic(f, author, form.title.data, th)
t.summary = form.summary.data
db.session.add(t)
db.session.commit()
@ -68,6 +69,10 @@ def forum_page(f, page=1):
for a, file in attachments:
a.set_file(file)
# If there's a thumbnail, set it
if form.thumbnail.data:
t.thumbnail = c.attachments[int(form.thumbnail.data)-1]
# Update member's xp and trophies
if current_user.is_authenticated:
current_user.add_xp(2) # 2 points for a topic

View File

@ -74,6 +74,12 @@ def edit_post(postid):
if isinstance(p, Topic):
p.title = form.title.data
p.summary = form.summary.data
# If there's a thumbnail, set it
if form.thumbnail.data:
p.thumbnail = comment.attachments[int(form.thumbnail.data)-1]
else:
p.thumbnail = None
f = Forum.query.filter_by(url=form.forum.data).first_or_404()
if current_user.can_post_in_forum(f):
p.forum = f
@ -102,6 +108,7 @@ def edit_post(postid):
form.message.data = p.thread.top_comment.text
form.title.data = p.title
form.forum.data = p.forum.url
form.summary.data = p.summary
return render('forum/edit_topic.html', t=p, form=form)
@app.route('/post/supprimer/<int:postid>', methods=['GET','POST'])

View File

@ -48,6 +48,22 @@
{% endfor %}
</div>
<div>
{{ form.summary.label }}
{{ form.summary }}
{% for error in form.summary.errors %}
<span class="msgerror">{{ error }}</span>
{% endfor %}
</div>
<div>
{{ form.thumbnail.label }}
{{ form.thumbnail }}
{% for error in form.thumbnail.errors %}
<span class="msgerror">{{ error }}</span>
{% endfor %}
</div>
{% if form.pseudo %}
<div>
{{ form.pseudo.label }}

View File

@ -75,6 +75,22 @@
{% endfor %}
</div>
<div>
{{ form.summary.label }}
{{ form.summary }}
{% for error in form.summary.errors %}
<span class="msgerror">{{ error }}</span>
{% endfor %}
</div>
<div>
{{ form.thumbnail.label }}
{{ form.thumbnail }}
{% for error in form.thumbnail.errors %}
<span class="msgerror">{{ error }}</span>
{% endfor %}
</div>
{{ widget_editor.text_editor(form.message) }}
<div>

View File

@ -15,6 +15,10 @@
<section>
<h1>{{ t.title }}</h1>
{% if t.summary %}
<div>{{ t.summary | md }}</div>
{% endif %}
{% if t.thread.top_comment %}
{% call widget_thread.thread_leader(t.thread.top_comment) %}
<div class="info">

View File

@ -46,63 +46,18 @@
<div class="home-news">
<h1>Actualitées</h1>
<ul>
{% for n in last_news %}
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/tdm9_collision2.jpg"/></a>
<a href="{{ url_for('forum_topic', f=n.forum, page=(n,'fin'))}}"><img src="{{ n.thumbnail.url }}"/></a>
<div>
<h3><a href="#">Les collisions — partie 2</a></h3>
<p class="date"><i>Publié par <a href="#">Shadow15510</a> le <time>09/06/2023 09:10</time></i></p>
La deuxième partie du tutoriel du mercredi sur les collisions est maintenant disponible en vidéo.
<h3><a href="{{ url_for('forum_topic', f=n.forum, page=(n,'fin'))}}">{{ n.title }}</a></h3>
<p class="date"><i>Publié par <a href="{{ url_for('user_by_id', user_id=n.author.id) }}">{{ n.author.name }}</a>
le <time>{{ n.date_created | dyndate }}</time></i></p>
{{ (n.summary or "") | md }}
</div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/CPC30-image-thumb-results.png"/></a>
<div>
<h3><a href="#">Résultats du CPC #30 — Les profondeurs !</a>
</h3>
<p class="date"><i>Publié par <a href="#">Lephenixnoir</a> le <time>08/06/2023 22:10</time></i></p>
Les programmes sont profonds et avec un peu de chance les tests aussi ! </div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/tituya-thumb.png"/></a>
<div>
<h3><a href="#">Un second renardministrateur !</a>
</h3>
<p class="date"><i>Publié par <a href="#">Lephenixnoir</a> le <time>07/06/2023 22:55</time></i></p>
Vive la renardocratie ! </div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/massy2.jpg"/></a>
<div>
<h3><a href="#">Visite chez Casio France à Massy, musée inclus</a>
</h3>
<p class="date"><i>Publié par <a href="#">Critor</a> le <time>05/06/2023 11:51</time></i></p>
Compte-rendu de notre visite au sein même des locaux de Casio France à Massy en mai 2023, passage par leur musée privé inclus. </div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/CPC30-image-title.jpg"/></a>
<div>
<h3><a href="#">Le CPC#30 - Les Profondeurs ... C'est désormais terminé ... Bravo à tous les participants.</a>
</h3>
<p class="date"><i>Publié par <a href="#">Slyvtt</a> le <time>03/06/2023 21:36</time></i></p>
Aujourd'hui sonne la fin du CPC#30 avec à la clef 6 participations pour vous donner du fun. Graphs Monochromes et Couleurs sont à la fête avec des programmes en Basic et des Addins. </div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/tdm9_miniature.jpg"/></a>
<div>
<h3><a href="#">Les Tutos du Mercredi débarquent sur Youtube !</a>
</h3>
<p class="date"><i>Publié par <a href="#">Shadow15510</a> le <time>29/05/2023 14:15</time></i></p>
</div>
</li>
<li>
<a href="#"><img src="https://www.planet-casio.com/images/staff/CPC30-image-thumb.jpg"/></a>
<div>
<h3><a href="#">Le CPC #30 - Les profondeurs !</a>
</h3>
<p class="date"><i>Publié par <a href="#">Lephenixnoir</a> le <time>27/05/2023 18:00</time></i></p>
Le concours CPC revient en force et c'est le moment de se plonger (métaphoriquement <i>et</i> littéralement !) dans le game design fin et la programmation sportive. Une semaine pour les programmer tous, et dans les profondeurs les li— oups ! </div>
</li>
<li><p><i><a href="https://www.planet-casio.com/Fr/forums/partie6-.html">Voir toutes les news</a></i></p></li>
{% endfor %}
<li><p><i><a href="/forum/actus/">Voir toutes les news</a></i></p></li>
</ul>
</div>
<div class="home-shoutbox" style="border: 1px solid #737373; padding: 20px">

View File

@ -56,3 +56,13 @@ def own_title(form, title):
return True
else:
return False
def attachment_exists(form, number):
try:
n = int(number.data)
if n <= 0 or n > len(form.attachments.data):
raise Exception()
except Exception as e:
raise ValidationError('Lillustration doit être le numéro dune pièce-jointe')
return True

View File

@ -0,0 +1,36 @@
"""Topics: add summary and thumbnail
Revision ID: a8f539a93bd5
Revises: 5ffc4e562ed8
Create Date: 2023-07-25 21:44:55.782425
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'a8f539a93bd5'
down_revision = '5ffc4e562ed8'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('topic', schema=None) as batch_op:
batch_op.add_column(sa.Column('summary', sa.UnicodeText(), nullable=True))
batch_op.add_column(sa.Column('thumbnail_id', postgresql.UUID(as_uuid=True), nullable=True))
batch_op.create_foreign_key(None, 'attachment', ['thumbnail_id'], ['id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('topic', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('thumbnail_id')
batch_op.drop_column('summary')
# ### end Alembic commands ###