mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 11:26:56 -08:00
comment edit, delete, report, block
This commit is contained in:
parent
8def5b9afc
commit
0b159edf0a
15 changed files with 337 additions and 12 deletions
|
@ -425,7 +425,8 @@ def process_inbox_request(request_json, activitypublog_id):
|
||||||
score=instance_weight(user.ap_domain),
|
score=instance_weight(user.ap_domain),
|
||||||
ap_id=request_json['object']['id'],
|
ap_id=request_json['object']['id'],
|
||||||
ap_create_id=request_json['id'],
|
ap_create_id=request_json['id'],
|
||||||
ap_announce_id=None)
|
ap_announce_id=None,
|
||||||
|
instance_id=user.instance_id)
|
||||||
if 'source' in request_json['object'] and \
|
if 'source' in request_json['object'] and \
|
||||||
request_json['object']['source']['mediaType'] == 'text/markdown':
|
request_json['object']['source']['mediaType'] == 'text/markdown':
|
||||||
post_reply.body = request_json['object']['source']['content']
|
post_reply.body = request_json['object']['source']['content']
|
||||||
|
@ -530,7 +531,8 @@ def process_inbox_request(request_json, activitypublog_id):
|
||||||
nsfl=community.nsfl,
|
nsfl=community.nsfl,
|
||||||
ap_id=request_json['object']['object']['id'],
|
ap_id=request_json['object']['object']['id'],
|
||||||
ap_create_id=request_json['object']['id'],
|
ap_create_id=request_json['object']['id'],
|
||||||
ap_announce_id=request_json['id'])
|
ap_announce_id=request_json['id'],
|
||||||
|
instance_id=user.instance_id)
|
||||||
if 'source' in request_json['object']['object'] and \
|
if 'source' in request_json['object']['object'] and \
|
||||||
request_json['object']['object']['source']['mediaType'] == 'text/markdown':
|
request_json['object']['object']['source']['mediaType'] == 'text/markdown':
|
||||||
post_reply.body = request_json['object']['object']['source']['content']
|
post_reply.body = request_json['object']['object']['source']['content']
|
||||||
|
|
|
@ -56,7 +56,7 @@ def register(app):
|
||||||
db.create_all()
|
db.create_all()
|
||||||
private_key, public_key = RsaKeys.generate_keypair()
|
private_key, public_key = RsaKeys.generate_keypair()
|
||||||
db.session.add(Site(name="PieFed", description='', public_key=public_key, private_key=private_key))
|
db.session.add(Site(name="PieFed", description='', public_key=public_key, private_key=private_key))
|
||||||
db.session.add(Instance(domain=app.config['SERVER_NAME'], software='PieFed'))
|
db.session.add(Instance(domain=app.config['SERVER_NAME'], software='PieFed')) # Instance 1 is always the local instance
|
||||||
db.session.add(Settings(name='allow_nsfw', value=json.dumps(False)))
|
db.session.add(Settings(name='allow_nsfw', value=json.dumps(False)))
|
||||||
db.session.add(Settings(name='allow_nsfl', value=json.dumps(False)))
|
db.session.add(Settings(name='allow_nsfl', value=json.dumps(False)))
|
||||||
db.session.add(Settings(name='allow_dislike', value=json.dumps(True)))
|
db.session.add(Settings(name='allow_dislike', value=json.dumps(True)))
|
||||||
|
|
|
@ -590,6 +590,7 @@ class PostReply(db.Model):
|
||||||
parent_id = db.Column(db.Integer)
|
parent_id = db.Column(db.Integer)
|
||||||
root_id = db.Column(db.Integer)
|
root_id = db.Column(db.Integer)
|
||||||
depth = db.Column(db.Integer, default=0)
|
depth = db.Column(db.Integer, default=0)
|
||||||
|
instance_id = db.Column(db.Integer, db.ForeignKey('instance.id'), index=True)
|
||||||
body = db.Column(db.Text)
|
body = db.Column(db.Text)
|
||||||
body_html = db.Column(db.Text)
|
body_html = db.Column(db.Text)
|
||||||
body_html_safe = db.Column(db.Boolean, default=False)
|
body_html_safe = db.Column(db.Boolean, default=False)
|
||||||
|
@ -738,6 +739,7 @@ class Instance(db.Model):
|
||||||
updated_at = db.Column(db.DateTime, default=utcnow)
|
updated_at = db.Column(db.DateTime, default=utcnow)
|
||||||
|
|
||||||
posts = db.relationship('Post', backref='instance', lazy='dynamic')
|
posts = db.relationship('Post', backref='instance', lazy='dynamic')
|
||||||
|
post_replies = db.relationship('PostReply', backref='instance', lazy='dynamic')
|
||||||
communities = db.relationship('Community', backref='instance', lazy='dynamic')
|
communities = db.relationship('Community', backref='instance', lazy='dynamic')
|
||||||
|
|
||||||
|
|
||||||
|
@ -850,7 +852,6 @@ class Report(db.Model):
|
||||||
suspect_user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
suspect_user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
||||||
suspect_post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
|
suspect_post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
|
||||||
suspect_post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'))
|
suspect_post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'))
|
||||||
suspect_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'))
|
|
||||||
created_at = db.Column(db.DateTime, default=utcnow)
|
created_at = db.Column(db.DateTime, default=utcnow)
|
||||||
updated = db.Column(db.DateTime, default=utcnow)
|
updated = db.Column(db.DateTime, default=utcnow)
|
||||||
|
|
||||||
|
|
|
@ -450,6 +450,13 @@ def post_options(post_id: int):
|
||||||
return render_template('post/post_options.html', post=post)
|
return render_template('post/post_options.html', post=post)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/options', methods=['GET'])
|
||||||
|
def post_reply_options(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
return render_template('post/post_reply_options.html', post=post, post_reply=post_reply)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/post/<int:post_id>/edit', methods=['GET', 'POST'])
|
@bp.route('/post/<int:post_id>/edit', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def post_edit(post_id: int):
|
def post_edit(post_id: int):
|
||||||
|
@ -471,6 +478,7 @@ def post_edit(post_id: int):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
post.flush_cache()
|
post.flush_cache()
|
||||||
flash(_('Your changes have been saved.'), 'success')
|
flash(_('Your changes have been saved.'), 'success')
|
||||||
|
# todo: federate edit
|
||||||
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
else:
|
else:
|
||||||
if post.type == constants.POST_TYPE_ARTICLE:
|
if post.type == constants.POST_TYPE_ARTICLE:
|
||||||
|
@ -513,7 +521,8 @@ def post_report(post_id: int):
|
||||||
form = ReportPostForm()
|
form = ReportPostForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
report = Report(reasons=form.reasons_to_string(form.reasons.data), description=form.description.data,
|
report = Report(reasons=form.reasons_to_string(form.reasons.data), description=form.description.data,
|
||||||
type=1, reporter_id=current_user.id, suspect_post_id=post.id)
|
type=1, reporter_id=current_user.id, suspect_user_id=post.author.id, suspect_post_id=post.id,
|
||||||
|
suspect_community_id=post.community.id)
|
||||||
db.session.add(report)
|
db.session.add(report)
|
||||||
|
|
||||||
# Notify moderators
|
# Notify moderators
|
||||||
|
@ -591,3 +600,118 @@ def post_mea_culpa(post_id: int):
|
||||||
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
|
|
||||||
return render_template('post/post_mea_culpa.html', title=_('I changed my mind'), form=form, post=post)
|
return render_template('post/post_mea_culpa.html', title=_('I changed my mind'), form=form, post=post)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/report', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def post_reply_report(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
form = ReportPostForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
report = Report(reasons=form.reasons_to_string(form.reasons.data), description=form.description.data,
|
||||||
|
type=1, reporter_id=current_user.id, suspect_post_id=post.id, suspect_community_id=post.community.id,
|
||||||
|
suspect_user_id=post_reply.author.id, suspect_post_reply_id=post_reply.id)
|
||||||
|
db.session.add(report)
|
||||||
|
|
||||||
|
# Notify moderators
|
||||||
|
for mod in post.community.moderators():
|
||||||
|
notification = Notification(user_id=mod.user_id, title=_('A comment has been reported'),
|
||||||
|
url=f"https://{current_app.config['SERVER_NAME']}/comment/{post_reply.id}",
|
||||||
|
author_id=current_user.id)
|
||||||
|
db.session.add(notification)
|
||||||
|
post_reply.reports += 1
|
||||||
|
# todo: Also notify admins for certain types of report
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# todo: federate report to originating instance
|
||||||
|
if not post.community.is_local() and form.report_remote.data:
|
||||||
|
...
|
||||||
|
|
||||||
|
flash(_('Comment has been reported, thank you!'))
|
||||||
|
return redirect(post.community.local_url())
|
||||||
|
elif request.method == 'GET':
|
||||||
|
form.report_remote.data = True
|
||||||
|
|
||||||
|
return render_template('post/post_reply_report.html', title=_('Report comment'), form=form, post=post, post_reply=post_reply)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/block_user', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def post_reply_block_user(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
existing = UserBlock.query.filter_by(blocker_id=current_user.id, blocked_id=post_reply.author.id).first()
|
||||||
|
if not existing:
|
||||||
|
db.session.add(UserBlock(blocker_id=current_user.id, blocked_id=post_reply.author.id))
|
||||||
|
db.session.commit()
|
||||||
|
flash(_('%(name)s has been blocked.', name=post_reply.author.user_name))
|
||||||
|
|
||||||
|
# todo: federate block to post_reply author instance
|
||||||
|
|
||||||
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/block_instance', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def post_reply_block_instance(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
existing = InstanceBlock.query.filter_by(user_id=current_user.id, instance_id=post_reply.instance_id).first()
|
||||||
|
if not existing:
|
||||||
|
db.session.add(InstanceBlock(user_id=current_user.id, instance_id=post_reply.instance_id))
|
||||||
|
db.session.commit()
|
||||||
|
flash(_('Content from %(name)s will be hidden.', name=post_reply.instance.domain))
|
||||||
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/edit', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def post_reply_edit(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
if post_reply.parent_id:
|
||||||
|
comment = PostReply.query.get_or_404(post_reply.parent_id)
|
||||||
|
else:
|
||||||
|
comment = None
|
||||||
|
form = NewReplyForm()
|
||||||
|
if post_reply.user_id == current_user.id or post.community.is_moderator():
|
||||||
|
if form.validate_on_submit():
|
||||||
|
post_reply.body = form.body.data
|
||||||
|
post_reply.body_html = markdown_to_html(form.body.data)
|
||||||
|
post_reply.notify_author = form.notify_author.data
|
||||||
|
post.community.last_active = utcnow()
|
||||||
|
post_reply.edited_at = utcnow()
|
||||||
|
db.session.commit()
|
||||||
|
post.flush_cache()
|
||||||
|
flash(_('Your changes have been saved.'), 'success')
|
||||||
|
# todo: federate edit
|
||||||
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||||
|
else:
|
||||||
|
form.body.data = post_reply.body
|
||||||
|
form.notify_author.data = not post_reply.notify_author
|
||||||
|
return render_template('post/post_reply_edit.html', title=_('Edit comment'), form=form, post=post, post_reply=post_reply,
|
||||||
|
comment=comment, markdown_editor=True)
|
||||||
|
else:
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/delete', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def post_reply_delete(post_id: int, comment_id: int):
|
||||||
|
post = Post.query.get_or_404(post_id)
|
||||||
|
post_reply = PostReply.query.get_or_404(comment_id)
|
||||||
|
community = post.community
|
||||||
|
if post_reply.user_id == current_user.id or community.is_moderator():
|
||||||
|
if post_reply.has_replies():
|
||||||
|
post_reply.body = 'Deleted by author' if post_reply.author.id == current_user.id else 'Deleted by moderator'
|
||||||
|
post_reply.body_html = markdown_to_html(post_reply.body)
|
||||||
|
else:
|
||||||
|
post_reply.delete_dependencies()
|
||||||
|
db.session.delete(post_reply)
|
||||||
|
g.site.last_active = community.last_active = utcnow()
|
||||||
|
db.session.commit()
|
||||||
|
post.flush_cache()
|
||||||
|
flash(_('Comment deleted.'))
|
||||||
|
# todo: federate delete
|
||||||
|
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
|
@ -618,6 +618,7 @@ fieldset legend {
|
||||||
}
|
}
|
||||||
.comment .comment_actions {
|
.comment .comment_actions {
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.comment .comment_actions a {
|
.comment .comment_actions a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
|
@ -337,6 +337,7 @@ nav, etc which are used site-wide */
|
||||||
|
|
||||||
.comment_actions {
|
.comment_actions {
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
|
position: relative;
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,6 +545,15 @@ nav.navbar {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment_actions_link {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 48px;
|
||||||
|
width: 41px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
width: 96%;
|
width: 96%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,15 @@ nav.navbar {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment_actions_link {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 48px;
|
||||||
|
width: 41px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
width: 96%;
|
width: 96%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,13 +89,14 @@
|
||||||
{{ comment['comment'].body_html | safe }}
|
{{ comment['comment'].body_html | safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if current_user.is_authenticated and current_user.verified %}
|
|
||||||
<div class="comment_actions hidable">
|
<div class="comment_actions hidable">
|
||||||
|
{% if current_user.is_authenticated and current_user.verified %}
|
||||||
{% if post.comments_enabled %}
|
{% if post.comments_enabled %}
|
||||||
<a href="{{ url_for('post.add_reply', post_id=post.id, comment_id=comment['comment'].id) }}" rel="nofollow"><span class="fe fe-reply"></span> reply</a>
|
<a href="{{ url_for('post.add_reply', post_id=post.id, comment_id=comment['comment'].id) }}" rel="nofollow"><span class="fe fe-reply"></span> reply</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a href="{{ url_for('post.post_reply_options', post_id=post.id, comment_id=comment['comment'].id) }}" class="comment_actions_link" rel="nofollow"><span class="fe fe-options" title="Options"> </span></a>
|
||||||
|
</div>
|
||||||
{% if comment['replies'] %}
|
{% if comment['replies'] %}
|
||||||
{% if comment['comment'].depth <= THREAD_CUTOFF_DEPTH %}
|
{% if comment['comment'].depth <= THREAD_CUTOFF_DEPTH %}
|
||||||
<div class="replies hidable">
|
<div class="replies hidable">
|
||||||
|
|
|
@ -26,16 +26,16 @@
|
||||||
<li><a href="{{ url_for('post.post_block_domain', post_id=post.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
<li><a href="{{ url_for('post.post_block_domain', post_id=post.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
||||||
{{ _('Block domain %(domain)s', domain=post.domain.name) }}</a></li>
|
{{ _('Block domain %(domain)s', domain=post.domain.name) }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if post.instance_id %}
|
{% if post.instance_id and post.instance_id != 1 %}
|
||||||
<li><a href="{{ url_for('post.post_block_instance', post_id=post.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
<li><a href="{{ url_for('post.post_block_instance', post_id=post.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
||||||
{{ _('Hide every post from %(name)s', name=post.instance.domain) }}</a></li>
|
{{ _("Hide every post from author's instance: %(name)s", name=post.instance.domain) }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li><a href="{{ url_for('post.post_report', post_id=post.id) }}" class="no-underline"><span class="fe fe-report"></span>
|
<li><a href="{{ url_for('post.post_report', post_id=post.id) }}" class="no-underline"><span class="fe fe-report"></span>
|
||||||
{{ _('Report to moderators') }}</a></li>
|
{{ _('Report to moderators') }}</a></li>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>{{ _('If you want to perform more than one of these (e.g. block and report), hold down Ctrl and click, then complete the operation in the new tabs that open.') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
85
app/templates/post/post_reply_edit.html
Normal file
85
app/templates/post/post_reply_edit.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% from 'bootstrap/form.html' import render_form %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<script src="/static/js/coolfieldset.js"></script>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-8 position-relative add_reply main_pane">
|
||||||
|
<fieldset class="coolfieldset mt-4"><legend class="w-auto">Original post</legend>
|
||||||
|
<h3>{{ post.title }}</h3>
|
||||||
|
{{ post.body_html | safe }}
|
||||||
|
</fieldset>
|
||||||
|
{% if comment %}
|
||||||
|
<fieldset class="coolfieldset mt-4"><legend class="w-auto">Comment you are replying to</legend>
|
||||||
|
{{ comment.body_html | safe}}
|
||||||
|
</fieldset>
|
||||||
|
{% endif %}
|
||||||
|
<div class="position-relative">
|
||||||
|
{{ render_form(form) }}
|
||||||
|
{% if markdown_editor %}
|
||||||
|
<script nonce="{{ session['nonce'] }}">
|
||||||
|
window.addEventListener("load", function () {
|
||||||
|
var downarea = new DownArea({
|
||||||
|
elem: document.querySelector('#body'),
|
||||||
|
resize: DownArea.RESIZE_VERTICAL,
|
||||||
|
hide: ['heading', 'bold-italic'],
|
||||||
|
value: {{ form.body.data | tojson | safe }}
|
||||||
|
});
|
||||||
|
setupAutoResize('body');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
{% if current_user.is_authenticated and community_membership(current_user, post.community) %}
|
||||||
|
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/unsubscribe">{{ _('Unsubscribe') }}</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/subscribe">{{ _('Subscribe') }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form method="get">
|
||||||
|
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card mt-3">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>{{ _('About community') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>{{ post.community.description|safe }}</p>
|
||||||
|
<p>{{ post.community.rules|safe }}</p>
|
||||||
|
{% if len(mods) > 0 and not post.community.private_mods %}
|
||||||
|
<h3>Moderators</h3>
|
||||||
|
<ol>
|
||||||
|
{% for mod in mods %}
|
||||||
|
<li><a href="/u/{{ mod.user_name }}">{{ mod.user_name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if is_moderator %}
|
||||||
|
<div class="card mt-3">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>{{ _('Community Settings') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><a href="#" class="btn btn-primary">{{ _('Moderate') }}</a></p>
|
||||||
|
<p><a href="#" class="btn btn-primary">{{ _('Settings') }}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
36
app/templates/post/post_reply_options.html
Normal file
36
app/templates/post/post_reply_options.html
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% from 'bootstrap/form.html' import render_form %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-login mx-auto">
|
||||||
|
<div class="card mt-5">
|
||||||
|
<div class="card-body p-6">
|
||||||
|
<div class="card-title">{{ _('Options for comment on "%(post_title)s"', post_title=post.title) }}</div>
|
||||||
|
<ul class="option_list">
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
{% if post_reply.user_id == current_user.id or post.community.is_moderator() %}
|
||||||
|
<li><a href="{{ url_for('post.post_reply_edit', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline" rel="nofollow"><span class="fe fe-edit"></span>
|
||||||
|
{{ _('Edit') }}</a></li>
|
||||||
|
<li><a href="{{ url_for('post.post_reply_delete', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete"></span>
|
||||||
|
{{ _('Delete') }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% if post_reply.user_id != current_user.id %}
|
||||||
|
<li><a href="{{ url_for('post.post_reply_block_user', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
||||||
|
{{ _('Block author @%(author_name)s', author_name=post_reply.author.user_name) }}</a></li>
|
||||||
|
{% if post_reply.instance_id and post_reply.instance_id != 1 %}
|
||||||
|
<li><a href="{{ url_for('post.post_reply_block_instance', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline"><span class="fe fe-block"></span>
|
||||||
|
{{ _("Hide every post from author's instance: %(name)s", name=post_reply.instance.domain) }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
<li><a href="{{ url_for('post.post_reply_report', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline"><span class="fe fe-report"></span>
|
||||||
|
{{ _('Report to moderators') }}</a></li>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<p>{{ _('If you want to perform more than one of these (e.g. block and report), hold down Ctrl and click, then complete the operation in the new tabs that open.') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
18
app/templates/post/post_reply_report.html
Normal file
18
app/templates/post/post_reply_report.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% from 'bootstrap/form.html' import render_form %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-login mx-auto">
|
||||||
|
<div class="card mt-5">
|
||||||
|
<div class="card-body p-6">
|
||||||
|
<div class="card-title">{{ _('Report comment on "%(post_title)s" by %(reply_name)s',
|
||||||
|
post_title=post.title, reply_name=post_reply.author.user_name) }}</div>
|
||||||
|
<div class="card-body">
|
||||||
|
{{ render_form(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
36
migrations/versions/e8113bc01e3a_post_reply_instance.py
Normal file
36
migrations/versions/e8113bc01e3a_post_reply_instance.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"""post reply instance
|
||||||
|
|
||||||
|
Revision ID: e8113bc01e3a
|
||||||
|
Revises: 52789c4b1d0f
|
||||||
|
Create Date: 2023-12-28 13:11:04.462308
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'e8113bc01e3a'
|
||||||
|
down_revision = '52789c4b1d0f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('post_reply', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('instance_id', sa.Integer(), nullable=True))
|
||||||
|
batch_op.create_index(batch_op.f('ix_post_reply_instance_id'), ['instance_id'], unique=False)
|
||||||
|
batch_op.create_foreign_key(None, 'instance', ['instance_id'], ['id'])
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('post_reply', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(None, type_='foreignkey')
|
||||||
|
batch_op.drop_index(batch_op.f('ix_post_reply_instance_id'))
|
||||||
|
batch_op.drop_column('instance_id')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
2
regional.txt
Normal file
2
regional.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
africa
|
||||||
|
https://baraza.africa/c/africa
|
Loading…
Reference in a new issue