forked from greyli/bluelog
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
216 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,29 @@ | |
:copyright: © 2018 Grey Li <[email protected]> | ||
:license: MIT, see LICENSE for more details. | ||
""" | ||
from flask import render_template, Blueprint | ||
from flask import render_template, flash, redirect, url_for, request, current_app, Blueprint, abort, make_response | ||
|
||
from bluelog.emails import send_new_comment_email, send_new_reply_email | ||
from bluelog.extensions import db | ||
from bluelog.forms import CommentForm, AdminCommentForm | ||
from bluelog.models import Post, Category, Comment | ||
from bluelog.utils import redirect_back | ||
|
||
blog_bp = Blueprint('blog', __name__) | ||
|
||
|
||
# skip it | ||
class current_user: | ||
is_authenticated = False | ||
|
||
|
||
@blog_bp.route('/') | ||
def index(): | ||
return render_template('blog/index.html') | ||
page = request.args.get('page', 1, type=int) | ||
per_page = current_app.config['BLUELOG_POST_PER_PAGE'] | ||
pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=per_page) | ||
posts = pagination.items | ||
return render_template('blog/index.html', pagination=pagination, posts=posts) | ||
|
||
|
||
@blog_bp.route('/about') | ||
|
@@ -22,9 +37,74 @@ def about(): | |
|
||
@blog_bp.route('/category/<int:category_id>') | ||
def show_category(category_id): | ||
return render_template('blog/category.html') | ||
category = Category.query.get_or_404(category_id) | ||
page = request.args.get('page', 1, type=int) | ||
per_page = current_app.config['BLUELOG_POST_PER_PAGE'] | ||
pagination = Post.query.with_parent(category).order_by(Post.timestamp.desc()).paginate(page, per_page) | ||
posts = pagination.items | ||
return render_template('blog/category.html', category=category, pagination=pagination, posts=posts) | ||
|
||
|
||
@blog_bp.route('/post/<int:post_id>', methods=['GET', 'POST']) | ||
def show_post(post_id): | ||
return render_template('blog/post.html') | ||
post = Post.query.get_or_404(post_id) | ||
page = request.args.get('page', 1, type=int) | ||
per_page = current_app.config['BLUELOG_COMMENT_PER_PAGE'] | ||
pagination = Comment.query.with_parent(post).filter_by(reviewed=True).order_by(Comment.timestamp.asc()).paginate( | ||
page, per_page) | ||
comments = pagination.items | ||
|
||
if current_user.is_authenticated: | ||
form = AdminCommentForm() | ||
form.author.data = current_user.name | ||
form.email.data = current_app.config['BLUELOG_EMAIL'] | ||
form.site.data = url_for('.index') | ||
from_admin = True | ||
reviewed = True | ||
else: | ||
form = CommentForm() | ||
from_admin = False | ||
reviewed = False | ||
|
||
if form.validate_on_submit(): | ||
author = form.author.data | ||
email = form.email.data | ||
site = form.site.data | ||
body = form.body.data | ||
comment = Comment( | ||
author=author, email=email, site=site, body=body, | ||
from_admin=from_admin, post=post, reviewed=reviewed) | ||
replied_id = request.args.get('reply') | ||
if replied_id: | ||
replied_comment = Comment.query.get_or_404(replied_id) | ||
comment.replied = replied_comment | ||
send_new_reply_email(replied_comment) | ||
db.session.add(comment) | ||
db.session.commit() | ||
if current_user.is_authenticated: # send message based on authentication status | ||
flash('Comment published.', 'success') | ||
else: | ||
flash('Thanks, your comment will be published after reviewed.', 'info') | ||
send_new_comment_email(post) # send notification email to admin | ||
return redirect(url_for('.show_post', post_id=post_id)) | ||
return render_template('blog/post.html', post=post, pagination=pagination, form=form, comments=comments) | ||
|
||
|
||
@blog_bp.route('/reply/comment/<int:comment_id>') | ||
def reply_comment(comment_id): | ||
comment = Comment.query.get_or_404(comment_id) | ||
if not comment.post.can_comment: | ||
flash('Comment is disabled.', 'warning') | ||
return redirect(url_for('.show_post', post_id=comment.post.id)) | ||
return redirect( | ||
url_for('.show_post', post_id=comment.post_id, reply=comment_id, author=comment.author) + '#comment-form') | ||
|
||
|
||
@blog_bp.route('/change-theme/<theme_name>') | ||
def change_theme(theme_name): | ||
if theme_name not in current_app.config['BLUELOG_THEMES'].keys(): | ||
abort(404) | ||
|
||
response = make_response(redirect_back()) | ||
response.set_cookie('theme', theme_name, max_age=30 * 24 * 60 * 60) | ||
return response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
{% extends 'base.html' %} | ||
{% from 'bootstrap/form.html' import render_form %} | ||
{% from 'bootstrap/pagination.html' import render_pagination %} | ||
|
||
{% block title %}{{ post.title }}{% endblock %} | ||
|
||
{% block content %} | ||
<div class="page-header"> | ||
<h1>{{ post.title }} | ||
<span class="float-right"> | ||
</span> | ||
</h1> | ||
<small> | ||
Category: <a | ||
href="{{ url_for('.show_category', category_id=post.category.id) }}">{{ post.category.name }}</a><br> | ||
Date: {{ moment(post.timestamp).format('LL') }} | ||
</small> | ||
</div> | ||
<div class="row"> | ||
<div class="col-sm-8"> | ||
{{ post.body|safe }} | ||
<hr> | ||
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target=".postLinkModal">Share | ||
</button> | ||
<div class="modal fade postLinkModal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" | ||
aria-hidden="true"> | ||
<div class="modal-dialog"> | ||
<div class="modal-content"> | ||
<div class="modal-header"> | ||
<h5 class="modal-title" id="exampleModalLabel">Permalink</h5> | ||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | ||
<span aria-hidden="true">×</span> | ||
</button> | ||
</div> | ||
<div class="modal-body"> | ||
<div class="form-group"> | ||
<input type="text" class="form-control" | ||
value="{{ url_for('.show_post', post_id=post.id, _external=True) }}" readonly> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="comments" id="comments"> | ||
<h3>{{ comments|length }} Comments | ||
<small> | ||
<a href="{{ url_for('.show_post', post_id=post.id, page=pagination.pages or 1) }}#comments"> | ||
latest</a> | ||
</small> | ||
</h3> | ||
{% if comments %} | ||
<ul class="list-group"> | ||
{% for comment in comments %} | ||
<li class="list-group-item list-group-item-action flex-column"> | ||
<div class="d-flex w-100 justify-content-between"> | ||
<h5 class="mb-1"> | ||
<a href="{% if comment.site %}{{ comment.site }}{% else %}#{% endif %}" | ||
target="_blank"> | ||
{% if comment.from_admin %} | ||
{{ admin.name }} | ||
{% else %} | ||
{{ comment.author }} | ||
{% endif %} | ||
</a> | ||
{% if comment.from_admin %} | ||
<span class="badge badge-primary">Author</span>{% endif %} | ||
{% if comment.replied %}<span class="badge badge-light">Reply</span>{% endif %} | ||
</h5> | ||
<small data-toggle="tooltip" data-placement="top" data-delay="500" | ||
data-timestamp="{{ comment.timestamp.strftime('%Y-%m-%dT%H:%M:%SZ') }}"> | ||
{{ moment(comment.timestamp).fromNow() }} | ||
</small> | ||
</div> | ||
{% if comment.replied %} | ||
<p class="alert alert-dark reply-body">{{ comment.replied.author }}: | ||
<br>{{ comment.replied.body }} | ||
</p> | ||
{%- endif -%} | ||
<p class="mb-1">{{ comment.body }}</p> | ||
<div class="float-right"> | ||
<a class="btn btn-light btn-sm" | ||
href="{{ url_for('.reply_comment', comment_id=comment.id) }}">Reply</a> | ||
</div> | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
{% else %} | ||
<div class="tip"><h5>No comments.</h5></div> | ||
{% endif %} | ||
</div> | ||
{% if comments %} | ||
{{ render_pagination(pagination, fragment='#comments') }} | ||
{% endif %} | ||
{% if request.args.get('reply') %} | ||
<div class="alert alert-dark"> | ||
Reply to <strong>{{ request.args.get('author') }}</strong>: | ||
<a class="float-right" href="{{ url_for('.show_post', post_id=post.id) }}">Cancel</a> | ||
</div> | ||
{% endif %} | ||
<div id="comment-form"> | ||
{{ render_form(form, action=request.full_path) }} | ||
</div> | ||
</div> | ||
<div class="col-sm-4 sidebar"> | ||
{% include "blog/_sidebar.html" %} | ||
</div> | ||
</div> | ||
{% endblock %} |