]> git.ipfire.org Git - people/jschlag/pbs.git/blame - web/ui_modules.py
Don't remove line breaks from comments.
[people/jschlag/pbs.git] / web / ui_modules.py
CommitLineData
f6e6ff79 1#!/usr/bin/python
9137135a 2
cd870d0a 3import pytz
f6e6ff79
MT
4import re
5import string
e434b018 6import textile
f6e6ff79 7import tornado.escape
9137135a
MT
8import tornado.web
9
f6e6ff79 10import backend.users
9137135a
MT
11from backend.constants import *
12
13class UIModule(tornado.web.UIModule):
14 @property
15 def pakfire(self):
16 return self.handler.application.pakfire
17
f6e6ff79
MT
18 @property
19 def settings(self):
20 return self.pakfire.settings
21
22
23class TextModule(UIModule):
c764ce43 24 __cache = {}
f6e6ff79 25
c764ce43 26 LINK = """<a href="%s" target="_blank">%s</a>"""
f6e6ff79 27
c764ce43
MT
28 @property
29 def bugzilla_url(self):
30 return self.settings.get("bugzilla_url", "")
f6e6ff79 31
c764ce43
MT
32 @property
33 def bugzilla_pattern(self):
34 if not self.__cache.has_key("bugzilla_pattern"):
35 self.__cache["bugzilla_pattern"] = re.compile(BUGZILLA_PATTERN)
36
37 return self.__cache["bugzilla_pattern"]
38
39 @property
40 def bugzilla_repl(self):
41 return self.LINK % (self.bugzilla_url % { "bugid" : r"\2" }, r"\1\2")
42
43 @property
44 def cve_url(self):
45 return self.settings.get("cve_url", "")
46
47 @property
48 def cve_pattern(self):
49 if not self.__cache.has_key("cve_pattern"):
50 self.__cache["cve_pattern"] = re.compile(CVE_PATTERN)
51
52 return self.__cache["cve_pattern"]
53
54 @property
55 def cve_repl(self):
56 return self.LINK % (self.cve_url % r"\3", r"\1\2\3")
c21cb4ec 57
c764ce43
MT
58 def render(self, text, pre=False, remove_linebreaks=True):
59 link = """<a href="%s" target="_blank">%s</a>"""
f6e6ff79 60
c764ce43
MT
61 if remove_linebreaks:
62 text = text.replace("\n", " ")
f6e6ff79 63
c764ce43
MT
64 # Escape the text and create make urls clickable.
65 text = tornado.escape.xhtml_escape(text)
66 text = tornado.escape.linkify(text, shorten=True,
67 extra_params='target="_blank"')
f6e6ff79 68
c764ce43
MT
69 # Search for bug ids that need to be linked to bugzilla.
70 if self.bugzilla_url:
71 text = re.sub(self.bugzilla_pattern, self.bugzilla_repl, text, re.I|re.U)
f6e6ff79 72
c764ce43
MT
73 # Search for CVE numbers and create hyperlinks.
74 if self.cve_url:
75 text = re.sub(self.cve_pattern, self.cve_repl, text, re.I|re.U)
f6e6ff79
MT
76
77 if pre:
c764ce43 78 return "<pre>%s</pre>" % text
f6e6ff79 79
c764ce43 80 return textile.textile(text)
f6e6ff79
MT
81
82
83class ModalModule(UIModule):
84 def render(self, what, **kwargs):
85 what = "modules/modal-%s.html" % what
9137135a 86
f6e6ff79
MT
87 return self.render_string(what, **kwargs)
88
89
90class BuildHeadlineModule(UIModule):
91 def render(self, prefix, build, short=False, shorter=False):
92 if shorter:
93 short = True
94
95 return self.render_string("modules/build-headline.html",
96 prefix=prefix, build=build, pkg=build.pkg, short=short, shorter=shorter)
97
98
99class BugsTableModule(UIModule):
100 def render(self, pkg, bugs):
101 return self.render_string("modules/bugs-table.html",
102 pkg=pkg, bugs=bugs)
103
104
4b1e87c4
MT
105class ChangelogModule(UIModule):
106 def render(self, name=None, builds=None, *args, **kwargs):
107 if not builds:
108 builds = self.pakfire.builds.get_changelog(name, *args, **kwargs)
109
110 return self.render_string("modules/changelog/index.html", builds=builds)
111
112
113class ChangelogEntryModule(UIModule):
114 def render(self, build):
115 return self.render_string("modules/changelog/entry.html", build=build)
116
117
f6e6ff79
MT
118class CommitsTableModule(UIModule):
119 def render(self, distro, source, commits, full_format=True):
120 return self.render_string("modules/commits-table.html",
121 distro=distro, source=source, commits=commits,
122 full_format=full_format)
123
124
125class FooterModule(UIModule):
126 def render(self):
127 return self.render_string("modules/footer.html")
128
129
130class PackagesTableModule(UIModule):
131 def render(self, job, packages):
132 return self.render_string("modules/packages-table.html", job=job,
133 packages=packages)
9137135a
MT
134
135
136class PackageTable2Module(UIModule):
137 def render(self, packages):
138 return self.render_string("modules/package-table-detail.html",
139 packages=packages)
140
141
142class FilesTableModule(UIModule):
143 def render(self, files):
144 return self.render_string("modules/files-table.html", files=files)
145
146
f6e6ff79
MT
147class LogFilesTableModule(UIModule):
148 def render(self, job, files):
149 return self.render_string("modules/log-files-table.html", job=job,
150 files=files)
151
152
153class PackageHeaderModule(UIModule):
154 def render(self, pkg):
155 return self.render_string("modules/package-header.html", pkg=pkg)
156
157
9137135a 158class PackageFilesTableModule(UIModule):
f6e6ff79
MT
159 def render(self, pkg, filelist):
160 return self.render_string("modules/packages-files-table.html",
161 pkg=pkg, filelist=filelist)
9137135a
MT
162
163
164class BuildTableModule(UIModule):
f6e6ff79
MT
165 def render(self, builds, **kwargs):
166 settings = dict(
167 show_user = False,
168 show_repo = False,
169 show_repo_time = False,
170 show_can_move_forward = False,
171 show_when = True,
172 )
173 settings.update(kwargs)
174
175 return self.render_string("modules/build-table.html",
176 builds=builds, **settings)
177
178
179class BuildStateWarningsModule(UIModule):
180 def render(self, build):
181 return self.render_string("modules/build-state-warnings.html", build=build)
182
183
3c7e0537
MT
184class JobsBoxesModule(UIModule):
185 def render(self, build, jobs=None):
186 if jobs is None:
187 jobs = build.jobs
188
189 return self.render_string("modules/jobs/boxes.html",
190 build=build, jobs=jobs)
191
192
193class JobStateModule(UIModule):
194 def render(self, job, cls=None):
195 state = job.state
196
197 _ = self.locale.translate
198 classes = []
199
200 if state == "aborted":
201 text = _("Aborted")
202 classes.append("muted")
203
204 elif state == "dependency_error":
205 text = _("Dependency problem")
206 classes.append("text-warning")
207
208 elif state == "dispatching":
209 text = _("Dispatching")
210 classes.append("text-info")
211
212 elif state == "failed":
213 text = _("Failed")
214 classes.append("text-error")
215
216 elif state == "finished":
217 text = _("Finished")
218 classes.append("text-success")
219
220 elif state == "new":
221 text = _("New")
222 classes.append("muted")
223
224 elif state == "pending":
225 text = _("Pending")
226 classes.append("muted")
227
228 elif state == "running":
229 text = _("Running")
230 classes.append("text-info")
231
232 # Return just the string, is state is unknown.
233 else:
234 text = _("Unknown: %s") % state
235 classes.append("muted")
236
237 if cls:
238 classes.append(cls)
239
240 return """<p class="%s">%s</p>""" % (" ".join(classes), text)
241
242
f6e6ff79
MT
243class JobsTableModule(UIModule):
244 def render(self, build, jobs=None, type="release"):
245 if jobs is None:
246 jobs = build.jobs
247
248 return self.render_string("modules/jobs-table.html", build=build,
249 jobs=jobs, type=type)
250
251
252class JobsListModule(UIModule):
253 def render(self, jobs, show_builder=False):
254 return self.render_string("modules/jobs-list.html", jobs=jobs,
255 show_builder=show_builder)
9137135a
MT
256
257
258class RepositoryTableModule(UIModule):
259 def render(self, distro, repos):
260 return self.render_string("modules/repository-table.html",
261 distro=distro, repos=repos)
262
263
264class SourceTableModule(UIModule):
265 def render(self, distro, sources):
266 return self.render_string("modules/source-table.html",
267 distro=distro, sources=sources)
268
269
270class CommentsTableModule(UIModule):
271 def render(self, comments, show_package=False, show_user=True):
272 pkgs, users = {}, {}
273 for comment in comments:
274 if show_package:
275 try:
276 pkg = pkgs[comment.pkg_id]
277 except KeyError:
278 pkg = pkgs[comment.pkg_id] = \
279 self.pakfire.packages.get_by_id(comment.pkg_id)
280
281 comment["pkg"] = pkg
282
283 if show_user:
284 try:
285 user = users[comment.user_id]
286 except KeyError:
287 user = users[comment.user_id] = \
288 self.pakfire.users.get_by_id(comment.user_id)
289
290 comment["user"] = user
291
292 return self.render_string("modules/comments-table.html",
293 comments=comments, show_package=show_package, show_user=show_user)
294
295
f6e6ff79
MT
296class LogModule(UIModule):
297 def render(self, entries, **args):
298 return self.render_string("modules/log.html",
299 entries=entries, args=args)
300
301
302class LogEntryModule(UIModule):
e434b018
MT
303 def render(self, entry, small=None, **args):
304 if small or entry.system_msg:
305 template = "modules/log-entry-small.html"
306 else:
307 template = "modules/log-entry.html"
308
309 return self.render_string(template, entry=entry, u=entry.user, **args)
f6e6ff79
MT
310
311
312class LogEntryCommentModule(LogEntryModule):
313 def render(self, entry, **args):
314 return self.render_string("modules/log-entry-comment.html",
e434b018 315 entry=entry, u=entry.user, **args)
f6e6ff79
MT
316
317
318class MaintainerModule(UIModule):
319 def render(self, maintainer):
320 if isinstance(maintainer, backend.users.User):
321 type = "user"
322 else:
323 type = "string"
324
325 return self.render_string("modules/maintainer.html",
326 type=type, maintainer=maintainer)
327
328
9137135a
MT
329class BuildLogModule(UIModule):
330 # XXX deprecated
331 def render(self, messages):
332 _ = self.locale.translate
333
334 for message in messages:
335 try:
336 msg = LOG2MSG[message.message]
337 message["message"] = _(msg)
338 except KeyError:
339 pass
340
341 return self.render_string("modules/build-log.html", messages=messages)
342
343
344class LogTableModule(UIModule):
345 def render(self, messages, links=["pkg",]):
346 for message in messages:
347 try:
348 message["message"] = LOG2MSG[message.message]
349 except KeyError:
350 pass
351
352 if message.build_id:
353 message["build"] = self.pakfire.builds.get_by_id(message.build_id)
354
355 elif message.pkg_id:
356 message["pkg"] = self.pakfire.packages.get_by_id(message.pkg_id)
357
358 return self.render_string("modules/log-table.html",
359 messages=messages, links=links)
360
361
362class UsersTableModule(UIModule):
363 def render(self, users):
364 return self.render_string("modules/user-table.html", users=users)
365
366
367class BuildOffsetModule(UIModule):
368 def render(self):
369 return self.render_string("modules/build-offset.html")
370
371
372class RepoActionsTableModule(UIModule):
373 def render(self, repo):
374 actions = repo.get_actions()
375
376 return self.render_string("modules/repo-actions-table.html",
377 repo=repo, actions=actions)
f6e6ff79
MT
378
379
380class UpdatesTableModule(UIModule):
381 def render(self, updates):
382 return self.render_string("modules/updates-table.html", updates=updates)
383
384
385class WatchersSidebarTableModule(UIModule):
386 def css_files(self):
387 return "css/watchers-sidebar-table.css"
388
389 def render(self, build, watchers, limit=5):
390 # Sort the watchers by their realname.
391 watchers.sort(key=lambda watcher: watcher.realname)
392
393 return self.render_string("modules/watchers-sidebar-table.html",
394 build=build, watchers=watchers, limit=limit)
cd870d0a
MT
395
396
397class SelectLocaleModule(UIModule):
398 LOCALE_NAMES = (
399 # local code, English name, name
400 ("ca_ES", u"Catalan", "Catal\xc3\xa0"),
401 ("da_DK", u"Danish", u"Dansk"),
402 ("de_DE", u"German", u"Deutsch"),
403 ("en_GB", u"English (UK)", u"English (UK)"),
404 ("en_US", u"English (US)", u"English (US)"),
405 ("es_ES", u"Spanish (Spain)", u"Espa\xf1ol (Espa\xf1a)"),
406 ("es_LA", u"Spanish", u"Espa\xf1ol"),
407 ("fr_CA", u"French (Canada)", u"Fran\xe7ais (Canada)"),
408 ("fr_FR", u"French", u"Fran\xe7ais"),
409 ("it_IT", u"Italian", u"Italiano"),
410 ("km_KH", u"Khmer", u"\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"),
411 ("pt_BR", u"Portuguese (Brazil)", u"Portugu\xeas (Brasil)"),
412 ("pt_PT", u"Portuguese (Portugal)", u"Portugu\xeas (Portugal)"),
413 ("ru_RU", u"Russian", u"\u0440\u0443\u0441\u0441\u043a\u0438\u0439"),
414 )
415
416 def render(self, name=None, id=None, preselect=None):
417 return self.render_string("modules/select/locale.html",
418 name=name, id=id, preselect=preselect, supported_locales=self.LOCALE_NAMES)
419
420
421class SelectTimezoneModule(UIModule):
422 def render(self, name=None, id=None, preselect=None):
423 return self.render_string("modules/select/timezone.html",
424 name=name, id=id, preselect=preselect,
425 supported_timezones=pytz.common_timezones)