<form class="form-horizontal" action="" method="POST" name="entry">
{% raw xsrf_form_html() %}
- {% if entry.id %}
+ {% if entry %}
<input type="hidden" name="id" value="{{ entry.id }}">
{% end %}
<label class="control-label" for="inputTitle">{{ _("Title") }}</label>
<div class="controls">
<input class="input-block-level" type="text" name="title" id="inputTitle"
- value="{{ entry.title }}" placeholder="{{ _("Title") }}">
+ {% if entry %}value="{{ entry.title }}"{% end %} placeholder="{{ _("Title") }}">
</div>
</div>
<div class="control-group">
<div class="controls">
<textarea class="input-block-level" name="markdown" rows="12" id="inputMarkdown"
- placeholder="{{ _("Content") }}">{{ entry.markdown }}</textarea>
+ placeholder="{{ _("Content") }}">{% if entry %}{{ entry.markdown }}{% end %}</textarea>
</div>
</div>
<label class="control-label" for="inputTags">{{ _("Tags") }}</label>
<div class="controls">
<input class="input-block-level planet-search-autocomplete" type="text"
- name="tags" id="inputTags" value="{{ " ".join(entry.tags) }}"
+ name="tags" id="inputTags" {% if entry %}value="{{ " ".join(entry.tags) }}"{% end %}
placeholder="{{ _("Tags") }}" autocomplete="off">
</div>
</div>
+
+ <hr>
+
+ <div class="control-group">
+ <label class="control-label" for="inputStatus">{{ _("Status") }}</label>
+ <div class="controls">
+ <label class="radio inline">
+ <input type="radio" name="inputStatus" value="draft" {% if not entry or not entry.is_published() %}checked{% end %}>
+ {{ _("Draft") }}
+ </label>
+ <label class="radio inline">
+ <input type="radio" name="inputStatus" value="published" {% if entry and entry.is_published() %}checked{% end %}>
+ {{ _("Published") }}
+ </label>
+ </div>
+ </div>
+
<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ _("Save") }}</button>
<a class="btn" href="javascript:preview();">{{ _("Preview") }}</a>
</tr>
{% for entry in entries %}
<tr>
- <td>{{ entry.author.cn }}</td>
- <td><a href="http://planet.ipfire.org/post/{{ entry.slug }}" target="_blank">{{ entry.title }}</a></td>
- <td><a href="/planet/edit/{{ entry.id }}">{{ _("Edit") }}</a></td>
+ <td>
+ {{ entry.author.cn }}
+ </td>
+ <td>
+ <a href="http://planet.ipfire.org/post/{{ entry.slug }}" target="_blank">{{ entry.title }}</a>
+ {% if entry.is_draft() %}
+ <span class="label label-warning">{{ _("Draft") }}</span>
+ {% end %}
+ </td>
+ <td>
+ <a href="/planet/edit/{{ entry.slug }}">{{ _("Edit") }}</a>
+ {% if entry.is_draft() %}
+ • <a href="/planet/publish/{{ entry.slug }}">{{ _("Publish") }}</a>
+ {% end %}
+ </td>
</tr>
{% end %}
</table>
<div class="row">
<div class="span9">
+ {% if entry.is_draft() %}
+ <div class="alert">
+ <button type="button" class="close" data-dismiss="alert">×</button>
+ <strong>{{ _("Heads up!") }}</strong> {{ _("This post is a draft and has not been published, yet.") }}
+ </div>
+ {% end %}
+
{% raw entry.text %}
</div>
# Planet
(r"/planet", AdminPlanetHandler),
(r"/planet/compose", AdminPlanetComposeHandler),
- (r"/planet/edit/([0-9]+)", AdminPlanetEditHandler),
+ (r"/planet/edit/(.*)", AdminPlanetEditHandler),
+ (r"/planet/publish/(.*)", AdminPlanetPublishHandler),
# Mirrors
(r"/mirrors", AdminMirrorsHandler),
(r"/mirrors/create", AdminMirrorsCreateHandler),
#!/usr/bin/python
+import datetime
import re
import textile
import tornado.database
def slug(self):
return self.data.slug
- @property
- def title(self):
- return self.data.title
+ def set_title(self, title):
+ if self.title == title:
+ return
+
+ self.db.execute("UPDATE planet SET title = %s WHERE id = %s", title, self.id)
+ self.data["title"] = title
+
+ title = property(lambda s: s.data.title, set_title)
@property
def url(self):
return "http://planet.ipfire.org/post/%s" % self.slug
- @property
- def published(self):
- return self.data.published
+ def set_published(self, published):
+ if self.published == published:
+ return
+
+ self.db.execute("UPDATE planet SET published = %s WHERE id = %s",
+ published, self.id)
+ self.data["published"] = published
+
+ published = property(lambda s: s.data.published, set_published)
@property
def year(self):
def updated(self):
return self.data.updated
- @property
- def markdown(self):
+ def get_markdown(self):
return self.data.markdown
+ def set_markdown(self, markdown):
+ if self.markdown == markdown:
+ return
+
+ markup = self.render(markdown)
+ self.db.execute("UPDATE planet SET markdown = %s, markup = %s WHERE id = %s",
+ markdown, markup, self.id)
+
+ self.data.update({
+ "markdown" : markdown,
+ "markup" : markup,
+ })
+
+ markdown = property(get_markdown, set_markdown)
+
@property
def markup(self):
if self.data.markup:
return self.__author
+ def set_status(self, status):
+ if self.status == status:
+ return
+
+ self.db.execute("UPDATE planet SET status = %s WHERE id = %s", status, self.id)
+ self.data["status"] = status
+
+ status = property(lambda s: s.data.status, set_status)
+
+ def is_draft(self):
+ return self.status == "draft"
+
+ def is_published(self):
+ return self.status == "published"
+
# Tags
def get_tags(self):
return slug
+ def create(self, title, markdown, author, status="published", tags=None, published=None):
+ slug = self._generate_slug(title)
+ markup = self.render(markdown)
+
+ if published is None:
+ published = datetime.datetime.utcnow()
+
+ id = self.db.execute("INSERT INTO planet(author_id, slug, title, status, \
+ markdown, markup, published) VALUES(%s, %s, %s, %s, %s, %s, %s)",
+ author.uid, slug, title, status, markdown, markup, published)
+
+ entry = self.get_entry_by_id(id)
+
+ if tags:
+ entry.tags = tags
+
+ return entry
+
def update_entry(self, entry):
self.db.execute("UPDATE planet SET title = %s, markdown = %s WHERE id = %s",
entry.title, entry.markdown, entry.id)
#!/usr/bin/python
+import datetime
import tornado.web
from handlers_base import *
import backend
class AdminBaseHandler(BaseHandler):
- @property
- def accounts(self):
- return backend.Accounts()
-
- @property
- def planet(self):
- return backend.Planet()
-
@property
def downloads(self):
return backend.Downloads()
output = {
"html" : self.planet.render(text),
}
- self.write(output)
- self.finish()
+ self.finish(output)
class AdminPlanetHandler(AdminBaseHandler):
@tornado.web.authenticated
def get(self):
- entries = self.planet.get_entries(limit=100)
+ entries = self.planet.get_entries(status=None, limit=100)
self.render("admin-planet.html", entries=entries)
class AdminPlanetComposeHandler(AdminBaseHandler):
@tornado.web.authenticated
- def get(self, id=None):
- entry = backend.PlanetEntry(self.planet.db)
+ def get(self, slug=None):
+ entry = None
- if id:
- entry = self.planet.get_entry_by_id(id)
+ if slug:
+ entry = self.planet.get_entry_by_slug(slug)
+ if not entry:
+ raise tornado.web.HTTPError(404)
self.render("admin-planet-compose.html", entry=entry)
@tornado.web.authenticated
- def post(self, id=None):
- id = self.get_argument("id", id)
+ def post(self):
+ title = self.get_argument("title")
+ markdown = self.get_argument("markdown")
+ tags = self.get_argument("tags", "")
- entry = backend.PlanetEntry(self.planet.db)
+ status = self.get_argument("status", "draft")
- if id:
- entry = self.planet.get_entry_by_id(id)
+ author = self.accounts.find(self.current_user)
- entry.set("title", self.get_argument("title"))
- entry.set("markdown", self.get_argument("markdown"))
- entry.set("author_id", self.current_user)
+ entry = self.planet.create(title=title, markdown=markdown,
+ author=author, status=status, tags=tags.split())
- if id:
- self.planet.update_entry(entry)
- else:
- id = self.planet.save_entry(entry)
- entry.id = id
+ self.redirect("/planet")
- tags = self.get_argument("tags", "")
- entry.tags = tags.split()
+
+class AdminPlanetEditHandler(AdminPlanetComposeHandler):
+ @tornado.web.authenticated
+ def post(self, slug):
+ entry = self.planet.get_entry_by_slug(slug)
+ if not entry:
+ raise tornado.web.HTTPError(404)
+
+ entry.title = self.get_argument("title")
+ entry.markdown = self.get_argument("markdown")
+ entry.tags = self.get_argument("tags", "").split()
+
+ entry.status = self.get_argument("status", "draft")
self.redirect("/planet")
-class AdminPlanetEditHandler(AdminPlanetComposeHandler):
- pass
+class AdminPlanetPublishHandler(AdminBaseHandler):
+ @tornado.web.authenticated
+ def get(self, slug):
+ entry = self.planet.get_entry_by_slug(slug)
+ if not entry:
+ raise tornado.web.HTTPError(404)
+
+ entry.status = "published"
+ entry.published = datetime.datetime.utcnow()
+
+ self.redirect("/planet")
class AdminAccountsBaseHandler(AdminBaseHandler):