]> git.ipfire.org Git - ipfire.org.git/blame - src/web/blog.py
CSS: Make background of outlined buttons slightly transparent
[ipfire.org.git] / src / web / blog.py
CommitLineData
12e5de7e
MT
1#!/usr/bin/python
2
9ea64cef 3import datetime
f0714277 4import email.utils
12e5de7e
MT
5import tornado.web
6
7import handlers_base as base
8
f91dfcc7
MT
9from . import ui_modules
10
8a897d25
MT
11class IndexHandler(base.BaseHandler):
12 def get(self):
0a6875dc 13 posts = self.backend.blog.get_newest(limit=3)
8a897d25
MT
14
15 self.render("blog/index.html", posts=posts)
16
17
cfc0823a
MT
18class AuthorHandler(base.BaseHandler):
19 def get(self, uid):
20 author = self.accounts.get_by_uid(uid)
21 if not author:
22 raise tornado.web.HTTPError(404, "User is unknown")
23
24 # Get all posts from this author
cdf85ee7 25 posts = self.backend.blog.get_by_author(author)
cfc0823a
MT
26 if not posts:
27 raise tornado.web.HTTPError(404, "User has no posts")
28
29 self.render("blog/author.html", author=author, posts=posts)
30
31
f0714277
MT
32class FeedHandler(base.BaseHandler):
33 def get(self):
34 cache_key = "%s-%s" % (self.request.host, self.request.path)
35
36 # Get feed from cache if possible
37 feed = self.memcached.get(cache_key)
38 if not feed:
0a6875dc 39 posts = self.backend.blog.get_newest(limit=50)
f0714277
MT
40
41 # Render the feed
42 feed = self.render_string("blog/feed.xml", posts=posts,
43 now=email.utils.formatdate())
44
45 # Store in cache for 5min
46 self.memcached.set(cache_key, feed, 300)
47
48 # Set correct content type
49 self.set_header("Content-Type", "application/rss+xml")
50
51 # Deliver content
52 self.finish(feed)
53
54
12e5de7e
MT
55class PostHandler(base.BaseHandler):
56 def get(self, slug):
df157ede 57 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
0a6875dc 58 if not post:
12e5de7e
MT
59 raise tornado.web.HTTPError(404)
60
0a6875dc 61 self.render("blog/post.html", post=post)
f91dfcc7
MT
62
63
9ea64cef
MT
64class PublishHandler(base.BaseHandler):
65 @tornado.web.authenticated
66 def post(self, slug):
67 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
68 if not post:
69 raise tornado.web.HTTPError(404)
70
71 # Is the post already published?
72 if post.is_published():
73 raise tornado.web.HTTPError(400, "Post is already published")
74
75 # Publish the post
76 with self.db.transaction():
77 post.publish()
78
79 self.redirect("/post/%s" % post.slug)
80
81
0b342a05
MT
82class DraftsHandler(base.BaseHandler):
83 @tornado.web.authenticated
84 def get(self):
85 drafts = self.backend.blog.get_drafts(author=self.current_user)
86
87 self.render("blog/drafts.html", drafts=drafts)
88
89
e6b18dce
MT
90class SearchHandler(base.BaseHandler):
91 def get(self):
92 q = self.get_argument("q")
93
0a6875dc 94 posts = self.backend.blog.search(q, limit=50)
e6b18dce
MT
95 if not posts:
96 raise tornado.web.HTTPError(404, "Nothing found")
97
98 self.render("blog/search-results.html", q=q, posts=posts)
99
100
4bde7f18
MT
101class TagHandler(base.BaseHandler):
102 def get(self, tag):
103 posts = self.backend.blog.get_by_tag(tag)
104 if not posts:
105 raise tornado.web.HTTPError(404, "There are no posts with tag: %s" % tag)
106
f0dc2fc1 107 self.render("blog/tag.html", posts=list(posts), tag=tag)
4bde7f18
MT
108
109
7e64f6a3
MT
110class YearHandler(base.BaseHandler):
111 def get(self, year):
112 posts = self.backend.blog.get_by_year(year)
113 if not posts:
114 raise tornado.web.HTTPError(404, "There are no posts in %s" % year)
115
116 self.render("blog/year.html", posts=posts, year=year)
117
118
541c952b
MT
119class ComposeHandler(base.BaseHandler):
120 @tornado.web.authenticated
121 def get(self):
122 self.render("blog/compose.html", post=None)
123
124 @tornado.web.authenticated
125 def post(self):
126 title = self.get_argument("title")
127 text = self.get_argument("text")
128 tags = self.get_argument("tags", None)
129
130 with self.db.transaction():
131 post = self.backend.blog.create_post(title, text,
132 author=self.current_user, tags=tags)
133
61e0a831 134 self.redirect("/drafts")
541c952b
MT
135
136
137class EditHandler(base.BaseHandler):
138 @tornado.web.authenticated
139 def get(self, slug):
00bf122b 140 post = self.backend.blog.get_by_slug(slug, published=False)
541c952b
MT
141 if not post:
142 raise tornado.web.HTTPError(404)
143
e8a81a70
MT
144 # Check if post is editable
145 if not post.is_editable(self.current_user):
146 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
541c952b
MT
147
148 self.render("blog/compose.html", post=post)
149
150 @tornado.web.authenticated
151 def post(self, slug):
00bf122b 152 post = self.backend.blog.get_by_slug(slug, published=False)
541c952b
MT
153 if not post:
154 raise tornado.web.HTTPError(404)
155
e8a81a70
MT
156 # Check if post is editable
157 if not post.is_editable(self.current_user):
158 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
541c952b 159
93725180 160 # Save updated content
541c952b 161 with self.db.transaction():
93725180
MT
162 post.update(
163 title = self.get_argument("title"),
164 text = self.get_argument("text"),
165 tags = self.get_argument("tags").split(),
166 )
541c952b
MT
167
168 # Return to blog if the post is already published
169 if post.is_published():
170 self.redirect("/post/%s" % post.slug)
171 return
172
61e0a831
MT
173 # Otherwise return to drafts
174 self.redirect("/drafts")
541c952b
MT
175
176
7e64f6a3
MT
177class HistoryNavigationModule(ui_modules.UIModule):
178 def render(self):
179 return self.render_string("blog/modules/history-navigation.html",
180 years=self.backend.blog.years)
181
182
183class ListModule(ui_modules.UIModule):
184 def render(self, posts):
185 return self.render_string("blog/modules/list.html", posts=posts)
186
187
f91dfcc7
MT
188class PostModule(ui_modules.UIModule):
189 def render(self, post):
190 return self.render_string("blog/modules/post.html", post=post)
8a897d25
MT
191
192
193class PostsModule(ui_modules.UIModule):
194 def render(self, posts):
0a6875dc 195 return self.render_string("blog/modules/posts.html", posts=list(posts))