progress on bookmarks / saving #26

This commit is contained in:
rimu 2024-06-20 21:51:43 +08:00
parent e9c2f70571
commit f85491218c
9 changed files with 139 additions and 2 deletions

View file

@ -1442,6 +1442,20 @@ class PollChoiceVote(db.Model):
created_at = db.Column(db.DateTime, default=utcnow)
class PostBookmark(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'), index=True)
created_at = db.Column(db.DateTime, default=utcnow)
class PostReplyBookmark(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'), index=True)
created_at = db.Column(db.DateTime, default=utcnow)
class IpBan(db.Model):
id = db.Column(db.Integer, primary_key=True)
ip_address = db.Column(db.String(50), index=True)

View file

@ -22,7 +22,8 @@ from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, SUBSCRIPTION_
POST_TYPE_ARTICLE, POST_TYPE_VIDEO, NOTIF_REPLY, NOTIF_POST, POST_TYPE_POLL
from app.models import Post, PostReply, \
PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community, \
Topic, User, Instance, NotificationSubscription, UserFollower, Poll, PollChoice, PollChoiceVote
Topic, User, Instance, NotificationSubscription, UserFollower, Poll, PollChoice, PollChoiceVote, PostBookmark, \
PostReplyBookmark
from app.post import bp
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
shorten_string, markdown_to_text, gibberish, ap_datetime, return_304, \
@ -1591,6 +1592,22 @@ def post_restore(post_id: int):
return redirect(url_for('activitypub.post_ap', post_id=post.id))
@bp.route('/post/<int:post_id>/bookmark', methods=['GET', 'POST'])
@login_required
def post_bookmark(post_id: int):
post = Post.query.get_or_404(post_id)
if post.deleted:
abort(404)
existing_bookmark = PostBookmark.query.filter(PostBookmark.post_id == post_id, PostBookmark.user_id == current_user.id).first()
if not existing_bookmark:
db.session.add(PostBookmark(post_id=post_id, user_id=current_user.id))
db.session.commit()
flash(_('Bookmark added.'))
else:
flash(_('This post has already been bookmarked.'))
return redirect(url_for('activitypub.post_ap', post_id=post.id))
@bp.route('/post/<int:post_id>/report', methods=['GET', 'POST'])
@login_required
def post_report(post_id: int):
@ -1786,7 +1803,7 @@ def post_reply_report(post_id: int, comment_id: int):
flash('Failed to send report to remote server', 'error')
flash(_('Comment has been reported, thank you!'))
return redirect(post.community.local_url())
return redirect(url_for('activitypub.post_ap', post_id=post.id))
elif request.method == 'GET':
form.report_remote.data = True
@ -1797,6 +1814,25 @@ def post_reply_report(post_id: int, comment_id: int):
)
@bp.route('/post/<int:post_id>/comment/<int:comment_id>/bookmark', methods=['GET'])
@login_required
def post_reply_bookmark(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.deleted or post_reply.deleted:
abort(404)
existing_bookmark = PostReplyBookmark.query.filter(PostReplyBookmark.post_reply_id == comment_id,
PostReplyBookmark.user_id == current_user.id).first()
if not existing_bookmark:
db.session.add(PostReplyBookmark(post_reply_id=comment_id, user_id=current_user.id))
db.session.commit()
flash(_('Bookmark added.'))
else:
flash(_('This comment has already been bookmarked.'))
return redirect(url_for('activitypub.post_ap', post_id=post.id, _anchor=f'comment_{comment_id}'))
@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):

View file

@ -243,6 +243,10 @@
content: "\e995";
}
.fe-bookmark::before {
content: "\e924";
}
.fe-expand::before {
content: "\e98e";
}

View file

@ -275,6 +275,10 @@ nav, etc which are used site-wide */
content: "\e995";
}
.fe-bookmark::before {
content: "\e924";
}
.fe-expand::before {
content: "\e98e";
}

View file

@ -274,6 +274,10 @@
content: "\e995";
}
.fe-bookmark::before {
content: "\e924";
}
.fe-expand::before {
content: "\e98e";
}
@ -687,6 +691,10 @@ div.navbar {
.option_list li {
margin-bottom: 15px;
}
.option_list li .fe {
position: relative;
top: 1px;
}
.field_hint {
margin-top: -15px;

View file

@ -272,6 +272,11 @@ div.navbar {
li {
margin-bottom: 15px;
.fe {
position: relative;
top: 1px;
}
}
}

View file

@ -26,6 +26,8 @@
{{ _('Delete') }}</a></li>
{% endif -%}
{% endif -%}
<li><a href="{{ url_for('post.post_bookmark', post_id=post.id) }}" class="no-underline" rel="nofollow"><span class="fe fe-bookmark"></span>
{{ _('Bookmark') }}</a></li>
{% if post.user_id == current_user.id and not post.mea_culpa -%}
<li><a href="{{ url_for('post.post_mea_culpa', post_id=post.id) }}" class="no-underline"><span class="fe fe-mea-culpa"></span>
{{ _("I made a mistake with this post and have changed my mind about the topic") }}</a></li>

View file

@ -26,6 +26,8 @@
{{ _('Delete') }}</a></li>
{% endif -%}
{% endif -%}
<li><a href="{{ url_for('post.post_reply_bookmark', post_id=post.id, comment_id=post_reply.id) }}" class="no-underline" rel="nofollow"><span class="fe fe-bookmark"></span>
{{ _('Bookmark') }}</a></li>
{% 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>

View file

@ -0,0 +1,62 @@
"""save posts
Revision ID: 745e3e985199
Revises: 1c51c3df2770
Create Date: 2024-06-20 21:32:11.695162
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '745e3e985199'
down_revision = '1c51c3df2770'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('post_bookmark',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('post_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['post_id'], ['post.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
with op.batch_alter_table('post_bookmark', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_post_bookmark_post_id'), ['post_id'], unique=False)
batch_op.create_index(batch_op.f('ix_post_bookmark_user_id'), ['user_id'], unique=False)
op.create_table('post_reply_bookmark',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('post_reply_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['post_reply_id'], ['post_reply.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
with op.batch_alter_table('post_reply_bookmark', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_post_reply_bookmark_post_reply_id'), ['post_reply_id'], unique=False)
batch_op.create_index(batch_op.f('ix_post_reply_bookmark_user_id'), ['user_id'], unique=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('post_reply_bookmark', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_post_reply_bookmark_user_id'))
batch_op.drop_index(batch_op.f('ix_post_reply_bookmark_post_reply_id'))
op.drop_table('post_reply_bookmark')
with op.batch_alter_table('post_bookmark', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_post_bookmark_user_id'))
batch_op.drop_index(batch_op.f('ix_post_bookmark_post_id'))
op.drop_table('post_bookmark')
# ### end Alembic commands ###