src/templates/blog/feed.xml \
src/templates/blog/index.html \
src/templates/blog/post.html \
+ src/templates/blog/publish.html \
src/templates/blog/search-results.html \
src/templates/blog/tag.html \
src/templates/blog/year.html
<button type="submit" class="btn btn-primary btn-block">
{{ _("Save") }}
</button>
+
+ {% if post %}
+ <a class="btn btn-outline-primary btn-block" href="/post/{{ post.slug }}/delete">
+ {{ _("Delete") }}
+ </a>
+ {% end %}
</form>
</div>
</div>
{% else %}
{{ _("Not published") }}
{% end %}
-
- {% if current_user and current_user == post.author %}
- <a href="/post/{{ post.slug }}/edit">{{ _("Edit") }}</a>
- <a href="/post/{{ post.slug }}/delete">{{ _("Delete") }}</a>
- {% end %}
</p>
</div>
+ {% if not post.is_published() and post.is_editable(current_user) %}
+ <div class="row">
+ <div class="col-12 col-md-6 mb-3">
+ <a class="btn btn-success btn-block" href="/post/{{ post.slug }}/edit">
+ <span class="fas fa-edit mr-2"></span> {{ _("Edit") }}
+ </a>
+ </div>
+
+ <div class="col-12 col-md-6 mb-3">
+ <a class="btn btn-primary btn-block" href="/post/{{ post.slug }}/publish">
+ <span class="fas fa-book-reader mr-2"></span> {{ _("Publish") }}
+ </a>
+ </div>
+ </div>
+ {% end %}
+
<div class="blog-content">
{% raw post.html %}
</div>
</a>
{% end %}
</div>
-
- {% if not post.is_published() %}
- <form action="/post/{{ post.slug }}/publish" method="POST">
- {% raw xsrf_form_html() %}
-
- <div class="btn-toolbar mt-5">
- <button type="submit" class="btn btn-primary btn-block btn-lg">
- {{ _("Publish") }}
- </button>
- </div>
- </form>
- {% end %}
</div>
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}{{ _("Publish %s") % post.title }}{% end block %}
+
+{% block modal %}
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title mb-1">{{ _("Publish Post") }}</h5>
+ <h6 class="card-subtitle text-muted mb-3">{{ post.title }}</h6>
+
+ <form action="" method="POST">
+ {% raw xsrf_form_html() %}
+
+ <input type="hidden" name="when">
+
+ <div class="form-group">
+ <label>{{ _("Time to Publish") }}</label>
+
+ <input type="datetime-local" class="form-control"
+ pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}" required>
+ </div>
+
+ <button type="submit" class="btn btn-primary btn-block">{{ _("Publish") }}</button>
+ <a class="btn btn-secondary btn-block" href="/post/{{ post.slug }}">{{ _("Cancel") }}</a>
+ </form>
+ </div>
+ </div>
+{% end block %}
+
+{% block javascript %}
+ <script type="text/javascript">
+ $(document).ready(function() {
+ var when = $("input[name='when']");
+
+ $("input[type='datetime-local']").on("change keyup", function(event) {
+ var value = $(this).val();
+
+ // Parse date and format with timezone
+ if (value) {
+ var date = new Date(value);
+ value = date.toISOString();
+ }
+
+ when.val(value);
+ }).change();
+ });
+ </script>
+{% end %}
#!/usr/bin/python
import datetime
+import dateutil
import email.utils
import tornado.web
class PublishHandler(auth.CacheMixin, base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, slug):
+ post = self.backend.blog.get_by_slug(slug, published=False)
+ if not post:
+ raise tornado.web.HTTPError(404)
+
+ # Check if current_user is allowed to edit the post
+ if not post.is_editable(self.current_user):
+ raise tornado.web.HTTPError(403)
+
+ # Is the post already published?
+ if post.is_published():
+ raise tornado.web.HTTPError(400, "Post is already published")
+
+ self.render("blog/publish.html", post=post)
+
@tornado.web.authenticated
def post(self, slug):
- post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
+ post = self.backend.blog.get_by_slug(slug, published=False)
if not post:
raise tornado.web.HTTPError(404)
+ # Check if current_user is allowed to edit the post
+ if not post.is_editable(self.current_user):
+ raise tornado.web.HTTPError(403)
+
# Is the post already published?
if post.is_published():
raise tornado.web.HTTPError(400, "Post is already published")
- # XXX Check that we are only publishing our own posts
+ when = self.get_argument("when", None)
+ if when:
+ when = dateutil.parser.parse(when)
# Publish the post
with self.db.transaction():
- post.publish()
+ post.publish(when)
self.redirect("/post/%s" % post.slug)