]> git.ipfire.org Git - ipfire.org.git/blame - src/web/ui_modules.py
Drop news
[ipfire.org.git] / src / web / ui_modules.py
CommitLineData
81675874 1#!/usr/bin/python
2
91a446f0
MT
3from __future__ import division
4
de683d7c 5import hashlib
940227cb 6import logging
91a446f0 7import operator
9068dba1 8import re
940227cb
MT
9import socket
10import textile
11import tornado.escape
6af40477 12import tornado.locale
feb02477 13import tornado.web
9068dba1 14import unicodedata
81675874 15
a95c2f97 16from .. import database
494d80e6 17
81675874 18class UIModule(tornado.web.UIModule):
940227cb
MT
19 @property
20 def accounts(self):
21 return self.handler.accounts
81675874 22
a0048e66
MT
23 @property
24 def advertisements(self):
25 return self.handler.advertisements
26
d0d074e0 27 @property
940227cb
MT
28 def banners(self):
29 return self.handler.banners
d0d074e0 30
de683d7c
MT
31 @property
32 def memcached(self):
33 return self.handler.memcached
34
940227cb
MT
35 @property
36 def releases(self):
37 return self.handler.releases
81675874 38
638e9782
MT
39 @property
40 def geoip(self):
41 return self.handler.geoip
42
77431b9c
MT
43 @property
44 def talk(self):
45 return self.handler.talk
46
5a1018ab 47
a0048e66
MT
48class AdvertisementModule(UIModule):
49 def render(self, where):
50 assert where in ("download-splash",), where
51
52 ad = self.advertisements.get(where)
53 if not ad:
54 return ""
55
56 # Mark that advert has been shown.
57 ad.update_impressions()
58
59 return self.render_string("modules/ads/%s.html" % where, ad=ad)
60
61
66862195
MT
62class FireinfoDeviceTableModule(UIModule):
63 def render(self, devices):
64 return self.render_string("fireinfo/modules/table-devices.html",
65 devices=devices)
66
67
68class FireinfoDeviceAndGroupsTableModule(UIModule):
69 def render(self, devices):
70 _ = self.locale.translate
71
72 groups = {}
73
74 for device in devices:
75 if not groups.has_key(device.cls):
76 groups[device.cls] = []
77
78 groups[device.cls].append(device)
79
80 # Sort all devices
81 for key in groups.keys():
82 groups[key].sort()
83
84 # Order the groups by their name
85 groups = groups.items()
86 groups.sort()
87
88 return self.render_string("fireinfo/modules/table-devices-and-groups.html",
89 groups=groups)
90
91
92class FireinfoGeoTableModule(UIModule):
93 def render(self, items):
94 countries = []
95 other_countries = []
96 for code, value in items:
97 # Skip the satellite providers in this ranking
98 if code in (None, "A1", "A2"):
99 continue
100
101 name = self.geoip.get_country_name(code)
102
103 # Don't add countries with a small share on the list
104 if value < 0.01:
105 other_countries.append(name)
106 continue
107
a95c2f97 108 country = database.Row({
66862195
MT
109 "code" : code,
110 "name" : name,
111 "value" : value,
112 })
113 countries.append(country)
114
66862195
MT
115 return self.render_string("fireinfo/modules/table-geo.html",
116 countries=countries, other_countries=other_countries)
117
118
119class LanguageNameModule(UIModule):
120 def render(self, language):
121 _ = self.locale.translate
122
123 if language == "de":
124 return _("German")
125 elif language == "en":
126 return _("English")
127 elif language == "es":
128 return _("Spanish")
129 elif language == "fr":
130 return _("French")
131 elif language == "it":
132 return _("Italian")
133 elif language == "nl":
134 return _("Dutch")
135 elif language == "pl":
136 return _("Polish")
137 elif language == "pt":
138 return _("Portuguese")
139 elif language == "ru":
140 return _("Russian")
141 elif language == "tr":
142 return _("Turkish")
143
144 return language
145
146
9068dba1
MT
147class MapModule(UIModule):
148 def render(self, latitude, longitude):
149 return self.render_string("modules/map.html", latitude=latitude, longitude=longitude)
150
151
940227cb
MT
152class MenuModule(UIModule):
153 def render(self):
60024cc8 154 return self.render_string("modules/menu.html")
81675874 155
156
9068dba1
MT
157class MirrorItemModule(UIModule):
158 def render(self, item):
159 return self.render_string("modules/mirror-item.html", item=item)
160
161
162class MirrorsTableModule(UIModule):
163 def render(self, mirrors, preferred_mirrors=[]):
164 return self.render_string("modules/mirrors-table.html",
165 mirrors=mirrors, preferred_mirrors=preferred_mirrors)
166
167
168class NetBootMenuConfigModule(UIModule):
37b5c0cf
MT
169 def render(self, release, arch=None, platform=None):
170 return self.render_string("netboot/menu-config.cfg", release=release,
171 arch=arch, platform=platform)
9068dba1
MT
172
173
174class NetBootMenuHeaderModule(UIModule):
37b5c0cf 175 def render(self, title, releases, arch=None, platform=None):
9068dba1
MT
176 id = unicodedata.normalize("NFKD", unicode(title)).encode("ascii", "ignore")
177 id = re.sub(r"[^\w]+", " ", id)
178 id = "-".join(id.lower().strip().split())
179
180 return self.render_string("netboot/menu-header.cfg", id=id,
37b5c0cf 181 title=title, releases=releases, arch=arch, platform=platform)
9068dba1
MT
182
183
184class NetBootMenuSeparatorModule(UIModule):
185 def render(self):
186 return self.render_string("netboot/menu-separator.cfg")
187
188
81675874 189class SidebarItemModule(UIModule):
190 def render(self):
191 return self.render_string("modules/sidebar-item.html")
192
193
194class SidebarReleaseModule(UIModule):
81675874 195 def render(self):
196 return self.render_string("modules/sidebar-release.html",
940227cb 197 latest=self.releases.get_latest())
81675874 198
199
200class ReleaseItemModule(UIModule):
60024cc8 201 def render(self, release, latest=False):
6371bfda 202 arches = ("x86_64", "i586", "arm")
60024cc8 203
110e8687 204 downloads = []
6371bfda 205 for arch in arches:
110e8687
MT
206 files = []
207
208 for file in release.files:
209 if not file.arch == arch:
210 continue
211
212 files.append(file)
213
214 if files:
215 downloads.append((arch, files))
60024cc8
MT
216
217 return self.render_string("modules/release-item.html",
110e8687 218 release=release, latest=latest, downloads=downloads)
81675874 219
220
221class SidebarBannerModule(UIModule):
940227cb
MT
222 def render(self, item=None):
223 if not item:
224 item = self.banners.get_random()
225
81675874 226 return self.render_string("modules/sidebar-banner.html", item=item)
227
228
60024cc8
MT
229class DownloadButtonModule(UIModule):
230 def render(self, release, text="Download now!"):
231 best_image = None
232
233 for file in release.files:
6371bfda
MT
234 if (release.sname < "ipfire-2.19-core100" or file.arch == "x86_64") \
235 and file.type == "iso":
60024cc8
MT
236 best_image = file
237 break
238
239 # Show nothing when there was no image found.
240 if not best_image:
241 return ""
242
243 return self.render_string("modules/download-button.html",
244 release=release, image=best_image)
245
246
66862195
MT
247class ProgressBarModule(UIModule):
248 def render(self, value, colour=None):
249 value *= 100
250
251 return self.render_string("modules/progress-bar.html",
252 colour=colour, value=value)
253
254
5ac74b02 255class TalkContactModule(UIModule):
56851b01 256 def render(self, number, name=None, application=None):
5ac74b02
MT
257 account = self.accounts.get_by_sip_id(number)
258
259 return self.render_string("talk/modules/contact.html",
56851b01 260 account=account, number=number, name=name, application=application)
5ac74b02
MT
261
262
66862195 263class TalkCallLogModule(UIModule):
77431b9c
MT
264 def render(self, account=None, viewer=None):
265 if (account is None or not self.current_user == account) \
266 and not self.current_user.is_admin():
267 raise RuntimeException("Insufficient permissions")
268
269 if viewer is None:
270 viewer = self.current_user
271
272 calls = self.talk.get_call_log(account)
273
274 return self.render_string("talk/modules/call-log.html",
275 calls=calls, viewer=viewer)
276
277
278class TalkLinesModule(UIModule):
279 def render(self, account=None, show_account=False):
280 if (account is None or not self.current_user == account) \
281 and not self.current_user.is_admin():
282 raise RuntimeException("Insufficient permissions")
283
284 lines = self.talk.get_lines(account)
285
286 return self.render_string("talk/modules/lines.html",
287 show_account=show_account, lines=lines)
66862195
MT
288
289
290class TalkOngoingCallsModule(UIModule):
5ac74b02 291 def render(self, account=None, debug=False):
77431b9c
MT
292 if (account is None or not self.current_user == account) \
293 and not self.current_user.is_admin():
294 raise RuntimeException("Insufficient permissions")
295
5ac74b02 296 channels = self.talk.get_channels()
77431b9c 297
5ac74b02
MT
298 return self.render_string("talk/modules/ongoing-calls.html",
299 account=account, channels=channels, debug=debug)
66862195
MT
300
301
7771acea 302class DonationBoxModule(UIModule):
e00c06b9 303 def render(self, reason_for_transfer=None):
353880e5
MT
304 if reason_for_transfer:
305 reason_for_transfer = "IPFire.org - %s" % reason_for_transfer
306
307 return self.render_string("modules/donation-box.html",
e00c06b9
MT
308 reason_for_transfer=reason_for_transfer)
309
310
311class DonationButtonModule(UIModule):
069e18f5
MT
312 # https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/
313 COUNTRIES = (
314 "AU",
315 "AT",
316 "BE",
317 "BR",
318 "CA",
319 "CH",
320 "CN",
321 "DE",
322 "ES",
323 "GB",
324 "FR",
325 "IT",
326 "NL",
327 "PL",
328 "PT",
329 "RU",
330 "US",
331 )
332
333 LOCALES = (
334 "da_DK",
335 "he_IL",
336 "id_ID",
337 "ja_JP",
338 "no_NO",
339 "pt_BR",
340 "ru_RU",
341 "sv_SE",
342 "th_TH",
343 "zh_CN",
344 "zh_HK",
345 "zh_TW",
346 )
347
e00c06b9
MT
348 def render(self, reason_for_transfer=None, currency="EUR"):
349 if not reason_for_transfer:
350 reason_for_transfer = "IPFire.org"
351
352 primary = (currency == "EUR")
353
354 return self.render_string("modules/donation-button.html", primary=primary,
069e18f5
MT
355 reason_for_transfer=reason_for_transfer, currency=currency, lc=self.lc)
356
357 @property
358 def lc(self):
359 """
360 Returns the locale of the user
361 """
362 try:
363 locale, delimiter, encoding = self.locale.code.partition(".")
364
365 # Break for languages in specific countries
366 if locale in self.LOCALES:
367 return locale
368
369 lang, delimiter, country_code = locale.partition("_")
069e18f5
MT
370
371 if country_code and country_code in self.COUNTRIES:
372 return country_code
373
374 lang = lang.upper()
375 if lang in self.COUNTRIES:
376 return lang
377 except:
378 pass
379
380 # If anything goes wrong, fall back to GB
381 return "GB"
60b0917c
MT
382
383
384class DonationInputBoxModule(DonationButtonModule):
385 def render(self):
386 currencies = ("EUR", "USD", "GBP", "CHF", "AUD", "NZD", "CAD")
387
388 return self.render_string("modules/donation-input-box.html",
389 currencies=currencies, lc=self.lc)