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