]> git.ipfire.org Git - ipfire.org.git/blob - webapp/ui_modules.py
Major update of the webapp.
[ipfire.org.git] / webapp / ui_modules.py
1 #!/usr/bin/python
2
3 from __future__ import division
4
5 import hashlib
6 import logging
7 import operator
8 import re
9 import socket
10 import textile
11 import tornado.escape
12 import tornado.locale
13 import tornado.web
14 import unicodedata
15
16 from tornado.database import Row
17
18 import backend
19 import backend.stasy
20
21 class UIModule(tornado.web.UIModule):
22 @property
23 def accounts(self):
24 return self.handler.accounts
25
26 @property
27 def advertisements(self):
28 return self.handler.advertisements
29
30 @property
31 def banners(self):
32 return self.handler.banners
33
34 @property
35 def memcached(self):
36 return self.handler.memcached
37
38 @property
39 def releases(self):
40 return self.handler.releases
41
42 @property
43 def geoip(self):
44 return self.handler.geoip
45
46 @property
47 def news(self):
48 return self.handler.news
49
50
51 class AdvertisementModule(UIModule):
52 def render(self, where):
53 assert where in ("download-splash",), where
54
55 ad = self.advertisements.get(where)
56 if not ad:
57 return ""
58
59 # Mark that advert has been shown.
60 ad.update_impressions()
61
62 return self.render_string("modules/ads/%s.html" % where, ad=ad)
63
64
65 class MapModule(UIModule):
66 def render(self, latitude, longitude):
67 return self.render_string("modules/map.html", latitude=latitude, longitude=longitude)
68
69
70 class MenuModule(UIModule):
71 def render(self):
72 return self.render_string("modules/menu.html")
73
74
75 class MirrorItemModule(UIModule):
76 def render(self, item):
77 return self.render_string("modules/mirror-item.html", item=item)
78
79
80 class MirrorsTableModule(UIModule):
81 def render(self, mirrors, preferred_mirrors=[]):
82 return self.render_string("modules/mirrors-table.html",
83 mirrors=mirrors, preferred_mirrors=preferred_mirrors)
84
85
86 class NetBootMenuConfigModule(UIModule):
87 def render(self, release):
88 return self.render_string("netboot/menu-config.cfg", release=release)
89
90
91 class NetBootMenuHeaderModule(UIModule):
92 def render(self, title, releases):
93 id = unicodedata.normalize("NFKD", unicode(title)).encode("ascii", "ignore")
94 id = re.sub(r"[^\w]+", " ", id)
95 id = "-".join(id.lower().strip().split())
96
97 return self.render_string("netboot/menu-header.cfg", id=id,
98 title=title, releases=releases)
99
100
101 class NetBootMenuSeparatorModule(UIModule):
102 def render(self):
103 return self.render_string("netboot/menu-separator.cfg")
104
105
106 class NewsItemModule(UIModule):
107 def get_author(self, author):
108 # Get name of author
109 author = self.accounts.find(author)
110 if author:
111 return author.cn
112 else:
113 _ = self.locale.translate
114 return _("Unknown author")
115
116 def render(self, item, uncut=True, announcement=False, show_heading=True):
117 # Get author
118 item.author = self.get_author(item.author_id)
119
120 if not uncut and len(item.text) >= 400:
121 item.text = item.text[:400] + "..."
122
123 # Render text
124 item.text = textile.textile(item.text)
125
126 return self.render_string("modules/news-item.html", item=item,
127 uncut=uncut, announcement=announcement, show_heading=show_heading)
128
129
130 class NewsLineModule(UIModule):
131 def render(self, item):
132 return self.render_string("modules/news-line.html", item=item)
133
134
135 class NewsTableModule(UIModule):
136 def render(self, news):
137 return self.render_string("modules/news-table.html", news=news)
138
139
140 class NewsYearNavigationModule(UIModule):
141 def render(self, active=None):
142 try:
143 active = int(active)
144 except:
145 active = None
146
147 return self.render_string("modules/news-year-nav.html",
148 active=active, years=self.news.years)
149
150
151 class SidebarItemModule(UIModule):
152 def render(self):
153 return self.render_string("modules/sidebar-item.html")
154
155
156 class SidebarReleaseModule(UIModule):
157 def render(self):
158 return self.render_string("modules/sidebar-release.html",
159 latest=self.releases.get_latest())
160
161
162 class ReleaseItemModule(UIModule):
163 def render(self, release, latest=False):
164 files = {
165 "i586" : [],
166 "arm" : [],
167 }
168
169 for file in release.files:
170 try:
171 files[file.arch].append(file)
172 except KeyError:
173 pass
174
175 return self.render_string("modules/release-item.html",
176 release=release, latest=latest, files=files)
177
178
179 class SidebarBannerModule(UIModule):
180 def render(self, item=None):
181 if not item:
182 item = self.banners.get_random()
183
184 return self.render_string("modules/sidebar-banner.html", item=item)
185
186
187 class DownloadButtonModule(UIModule):
188 def render(self, release, text="Download now!"):
189 best_image = None
190
191 for file in release.files:
192 if file.type == "iso":
193 best_image = file
194 break
195
196 # Show nothing when there was no image found.
197 if not best_image:
198 return ""
199
200 return self.render_string("modules/download-button.html",
201 release=release, image=best_image)
202
203
204 class PlanetEntryModule(UIModule):
205 def render(self, entry, show_avatar=True):
206 return self.render_string("modules/planet-entry.html",
207 entry=entry, show_avatar=show_avatar)
208
209
210 class TrackerPeerListModule(UIModule):
211 def render(self, peers, percentages=False):
212 # Guess country code and hostname of the host
213 for peer in peers:
214 country_code = backend.GeoIP().get_country(peer["ip"])
215 peer["country_code"] = country_code or "unknown"
216
217 try:
218 peer["hostname"] = socket.gethostbyaddr(peer["ip"])[0]
219 except:
220 peer["hostname"] = ""
221
222 return self.render_string("modules/tracker-peerlist.html",
223 peers=[Row(p) for p in peers], percentages=percentages)
224
225
226 class StasyTableModule(UIModule):
227 def _make_percentages(self, items):
228 total = sum(items.values())
229
230 for k in items.keys():
231 items[k] *= 100
232 items[k] /= total
233
234 return items
235
236 def render(self, items, sortby="key", reverse=False, percentage=False, flags=False, locale=False):
237 hundred_percent = 0
238 for v in items.values():
239 hundred_percent += v
240
241 keys = []
242 if sortby == "key":
243 keys = sorted(items.keys(), reverse=reverse)
244 elif sortby == "percentage":
245 keys = [k for k,v in sorted(items.items(), key=operator.itemgetter(1))]
246 if not reverse:
247 keys = reversed(keys)
248 else:
249 raise Exception, "Unknown sortby parameter was provided"
250
251 if hundred_percent:
252 _items = []
253 for k in keys:
254 if not percentage:
255 v = items[k] * 100 / hundred_percent
256 else:
257 v = items[k] * 100
258 _items.append((k, v))
259 items = _items
260
261 if items and type(items[0][0]) == type(()) :
262 _ = self.locale.translate
263 _items = []
264 for k, v in items:
265 k = _("%s to %s") % k
266 _items.append((k, v))
267 items = _items
268
269 if locale:
270 flags = False
271 locales = tornado.locale.LOCALE_NAMES
272 _items = []
273 for k, v in items:
274 if k:
275 for code, locale in locales.items():
276 if code.startswith(k):
277 k = locale["name"].split()[0]
278 _items.append((k, v))
279 items = _items
280
281 return self.render_string("modules/stasy-table.html", items=items, flags=flags)
282
283
284 class StasyCPUCoreTableModule(StasyTableModule):
285 def render(self, items):
286 items = self._make_percentages(items)
287
288 items = items.items()
289 items.sort()
290
291 return self.render_string("modules/stasy-table.html", items=items,
292 flags=None #XXX
293 )
294
295
296 class StasyDeviceTableModule(UIModule):
297 def render(self, devices):
298 groups = {}
299
300 for device in devices:
301 if not groups.has_key(device.cls):
302 groups[device.cls] = []
303
304 groups[device.cls].append(device)
305
306 return self.render_string("modules/stasy-table-devices.html",
307 groups=groups.items())
308
309
310 class StasyGeoTableModule(UIModule):
311 def render(self, items):
312 _ = self.locale.translate
313
314 # Sort all items by value
315 items = sorted(items.items(), key=operator.itemgetter(1), reverse=True)
316
317 countries = []
318 for code, value in items:
319 country = tornado.database.Row({
320 "code" : code.lower(),
321 "name" : _(self.geoip.get_country_name(code)),
322 "value" : value * 100,
323 })
324 countries.append(country)
325
326 return self.render_string("modules/stasy-table-geo.html", countries=countries)
327
328
329 class WishlistModule(UIModule):
330 def render(self, wishes, short=False):
331 return self.render_string("wishlist/modules/wishlist.html",
332 wishes=wishes, short=short)
333
334
335 class WishModule(UIModule):
336 def render(self, wish, short=False):
337 progress_bar = "progress-warning"
338
339 if wish.percentage >= 100:
340 progress_bar = "progress-success"
341
342 return self.render_string("wishlist/modules/wish.html",
343 wish=wish, short=short, progress_bar=progress_bar)
344
345
346 class DonationBoxModule(UIModule):
347 def render(self, reason_for_transfer=None):
348 if reason_for_transfer:
349 reason_for_transfer = "IPFire.org - %s" % reason_for_transfer
350
351 return self.render_string("modules/donation-box.html",
352 reason_for_transfer=reason_for_transfer)