]>
git.ipfire.org Git - people/jschlag/pbs.git/blob - src/web/ui_modules.py
3 from __future__
import division
15 from ..constants
import *
17 class UIModule(tornado
.web
.UIModule
):
20 return self
.handler
.application
.backend
23 class TextModule(UIModule
):
24 BUGZILLA_PATTERN
= re
.compile(r
"(?:bug\s?|#)(\d+)")
25 CVE_PATTERN
= re
.compile(r
"(?:CVE)[\s\-](\d{4}\-\d{4})")
27 LINK
= """<a href="%s" target="_blank" rel="noopener">%s</a>"""
29 def split_paragraphs(self
, s
):
30 for group_seperator
, line_iteration
in itertools
.groupby(s
.splitlines(True), key
=str.isspace
):
34 paragraph
= "".join(line_iteration
)
35 yield paragraph
.replace("\n", " ")
37 def render(self
, text
, pre
=False, remove_linebreaks
=True):
39 text
= text
.replace("\n", " ")
41 # Escape the text and create make urls clickable.
42 text
= tornado
.escape
.xhtml_escape(text
)
43 text
= tornado
.escape
.linkify(text
, shorten
=True,
44 extra_params
="target=\"_blank\" rel=\"noopener\"")
46 # Search for bug ids that need to be linked to bugzilla
47 text
= re
.sub(self
.BUGZILLA_PATTERN
, self
._bugzilla
_repl
, text
, re
.I|re
.U
)
49 # Search for CVE numbers and create hyperlinks.
50 text
= re
.sub(self
.CVE_PATTERN
, self
._cve
_repl
, text
, re
.I|re
.U
)
53 return "<pre>%s</pre>" % text
57 def _bugzilla_repl(self
, m
):
61 bug_url
= self
.backend
.bugzilla
.bug_url(bug_id
)
63 return self
.LINK
% (bug_url
, m
.group(0))
65 def _cve_repl(self
, m
):
66 return self
.LINK
% ("http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s" % m
.group(1), m
.group(0))
69 class CommitMessageModule(TextModule
):
70 def render(self
, commit
):
71 s
= "h5. %s\n\n" % commit
.subject
73 paragraphs
= self
.split_paragraphs(commit
.message
)
74 s
+= "\n\n".join(paragraphs
)
76 return TextModule
.render(self
, s
, remove_linebreaks
=False)
79 class ModalModule(UIModule
):
80 def render(self
, what
, **kwargs
):
81 what
= "modules/modal-%s.html" % what
83 return self
.render_string(what
, **kwargs
)
86 class BuildHeadlineModule(UIModule
):
87 def render(self
, build
, short
=False, shorter
=False):
91 return self
.render_string("modules/build-headline.html",
92 build
=build
, pkg
=build
.pkg
, short
=short
, shorter
=shorter
)
95 class JobsStatusModule(UIModule
):
96 def render(self
, build
):
97 return self
.render_string("modules/jobs/status.html",
98 build
=build
, jobs
=build
.jobs
)
101 class BugsTableModule(UIModule
):
102 def render(self
, pkg
, bugs
):
103 return self
.render_string("modules/bugs-table.html",
107 class ChangelogModule(UIModule
):
108 def render(self
, name
=None, builds
=None, *args
, **kwargs
):
110 builds
= self
.backend
.builds
.get_changelog(name
, *args
, **kwargs
)
112 return self
.render_string("modules/changelog/index.html", builds
=builds
)
115 class ChangelogEntryModule(UIModule
):
116 def render(self
, build
):
117 return self
.render_string("modules/changelog/entry.html", build
=build
)
120 class CommitsTableModule(UIModule
):
121 def render(self
, distro
, source
, commits
, full_format
=True):
122 return self
.render_string("modules/commits-table.html",
123 distro
=distro
, source
=source
, commits
=commits
,
124 full_format
=full_format
)
127 class FooterModule(UIModule
):
129 return self
.render_string("modules/footer.html")
132 class HeadingDateModule(UIModule
):
133 def render(self
, date
):
134 _
= self
.locale
.translate
136 # Check if this is today.
137 today
= datetime
.date
.today()
141 # Check if this was yesterday.
142 yesterday
= today
- datetime
.timedelta(days
=1)
143 if date
== yesterday
:
144 return _("Yesterday")
146 # Convert date to datetime.
147 date
= datetime
.datetime(date
.year
, date
.month
, date
.day
)
149 return self
.locale
.format_date(date
, shorter
=True, relative
=False)
152 class PackagesTableModule(UIModule
):
153 def render(self
, job
, packages
):
154 return self
.render_string("modules/packages-table.html", job
=job
,
158 class PackagesDependencyTableModule(UIModule
):
159 def render(self
, pkg
):
160 if pkg
.type == "source":
162 (None, pkg
.requires
),
166 ("provides", pkg
.provides
),
167 ("requires", pkg
.requires
),
168 ("prerequires", pkg
.prerequires
),
169 ("conflicts", pkg
.conflicts
),
170 ("obsoletes", pkg
.obsoletes
),
171 ("recommends", pkg
.recommends
),
172 ("suggests", pkg
.suggests
),
176 for name
, deps
in all_deps
:
178 has_deps
.append((name
, deps
))
181 span
= math
.floor(12 / len(has_deps
))
188 return self
.render_string("modules/packages/dependency-table.html",
189 pkg
=pkg
, dependencies
=has_deps
, span
=span
)
192 class PackageTable2Module(UIModule
):
193 def render(self
, packages
):
194 return self
.render_string("modules/package-table-detail.html",
198 class FilesTableModule(UIModule
):
199 def render(self
, files
):
200 return self
.render_string("modules/files-table.html", files
=files
)
203 class LogFilesTableModule(UIModule
):
204 def render(self
, job
, files
):
205 return self
.render_string("modules/log-files-table.html", job
=job
,
209 class PackageHeaderModule(UIModule
):
210 def render(self
, pkg
):
211 return self
.render_string("modules/package-header.html", pkg
=pkg
)
214 class PackageFilesTableModule(UIModule
):
215 def render(self
, pkg
, filelist
):
216 return self
.render_string("modules/packages-files-table.html",
217 pkg
=pkg
, filelist
=filelist
)
220 class BuildTableModule(UIModule
):
221 def render(self
, builds
, **kwargs
):
225 show_repo_time
= False,
226 show_can_move_forward
= False,
229 settings
.update(kwargs
)
235 dates
[b
.date
].append(b
)
239 dates
= sorted(dates
.items(), reverse
=True)
241 return self
.render_string("modules/build-table.html", dates
=dates
, **settings
)
244 class BuildStateWarningsModule(UIModule
):
245 def render(self
, build
):
246 return self
.render_string("modules/build-state-warnings.html", build
=build
)
249 class JobsBoxesModule(UIModule
):
250 def render(self
, build
, jobs
=None):
254 return self
.render_string("modules/jobs/boxes.html",
255 build
=build
, jobs
=jobs
)
258 class JobStateModule(UIModule
):
259 def render(self
, job
, cls
=None, show_arch
=False, show_icon
=False, plain
=False):
262 _
= self
.locale
.translate
266 if state
== "aborted":
268 classes
.append("muted")
269 icon
= "icon-warning-sign"
271 elif state
== "dependency_error":
272 text
= _("Dependency problem")
273 classes
.append("text-warning")
276 elif state
== "dispatching":
277 text
= _("Dispatching")
278 classes
.append("text-info")
279 icon
= "icon-download-alt"
281 elif state
== "failed":
283 classes
.append("text-error")
286 elif state
== "finished":
288 classes
.append("text-success")
293 classes
.append("muted")
294 icon
= "icon-asterisk"
296 elif state
== "pending":
298 classes
.append("muted")
301 elif state
== "running":
303 classes
.append("text-info")
306 elif state
== "uploading":
307 text
= _("Uploading")
308 classes
.append("text-info")
309 icon
= "icon-upload-alt"
311 # Return just the string, is state is unknown.
313 text
= _("Unknown: %s") % state
314 classes
.append("muted")
325 if show_icon
and icon
:
326 text
= """<i class="%s"></i> %s""" % (icon
, text
)
328 return """<span class="%s">%s</span>""" % (" ".join(classes
), text
)
331 class JobsTableModule(UIModule
):
332 def render(self
, build
, jobs
=None, type="release"):
336 return self
.render_string("modules/jobs-table.html", build
=build
,
337 jobs
=jobs
, type=type)
340 class JobsListModule(UIModule
):
341 def render(self
, jobs
):
342 return self
.render_string("modules/jobs/list.html", jobs
=jobs
)
345 class RepositoryTableModule(UIModule
):
346 def render(self
, distro
, repos
):
347 return self
.render_string("modules/repository-table.html",
348 distro
=distro
, repos
=repos
)
351 class SourceTableModule(UIModule
):
352 def render(self
, distro
, sources
):
353 return self
.render_string("modules/source-table.html",
354 distro
=distro
, sources
=sources
)
357 class CommentsTableModule(UIModule
):
358 def render(self
, comments
, show_package
=False, show_user
=True):
360 for comment
in comments
:
363 pkg
= pkgs
[comment
.pkg_id
]
365 pkg
= pkgs
[comment
.pkg_id
] = \
366 self
.backend
.packages
.get_by_id(comment
.pkg_id
)
372 user
= users
[comment
.user_id
]
374 user
= users
[comment
.user_id
] = \
375 self
.backend
.users
.get_by_id(comment
.user_id
)
377 comment
["user"] = user
379 return self
.render_string("modules/comments-table.html",
380 comments
=comments
, show_package
=show_package
, show_user
=show_user
)
383 class LogModule(UIModule
):
384 def render(self
, entries
, **args
):
385 return self
.render_string("modules/log.html",
386 entries
=entries
, args
=args
)
389 class LogEntryModule(UIModule
):
390 def render(self
, entry
, small
=None, **args
):
391 if small
or not entry
.user
:
392 template
= "modules/log-entry-small.html"
394 template
= "modules/log-entry.html"
396 return self
.render_string(template
, entry
=entry
, u
=entry
.user
,
397 show_build
=False, **args
)
400 class LogEntryCommentModule(LogEntryModule
):
401 def render(self
, entry
, show_build
=False, **args
):
402 return self
.render_string("modules/log-entry-comment.html",
403 entry
=entry
, u
=entry
.user
, show_build
=show_build
, **args
)
406 class MaintainerModule(UIModule
):
407 def render(self
, maintainer
):
408 if isinstance(maintainer
, users
.User
):
413 return self
.render_string("modules/maintainer.html",
414 type=type, maintainer
=maintainer
)
417 class BuildLogModule(UIModule
):
419 def render(self
, messages
):
420 _
= self
.locale
.translate
422 for message
in messages
:
424 msg
= LOG2MSG
[message
.message
]
425 message
["message"] = _(msg
)
429 return self
.render_string("modules/build-log.html", messages
=messages
)
432 class LogTableModule(UIModule
):
433 def render(self
, messages
, links
=["pkg",]):
434 for message
in messages
:
436 message
["message"] = LOG2MSG
[message
.message
]
441 message
["build"] = self
.backend
.builds
.get_by_id(message
.build_id
)
444 message
["pkg"] = self
.backend
.packages
.get_by_id(message
.pkg_id
)
446 return self
.render_string("modules/log-table.html",
447 messages
=messages
, links
=links
)
450 class UsersTableModule(UIModule
):
451 def render(self
, users
):
452 return self
.render_string("modules/user-table.html", users
=users
)
455 class BuildOffsetModule(UIModule
):
457 return self
.render_string("modules/build-offset.html")
460 class RepoActionsTableModule(UIModule
):
461 def render(self
, repo
):
462 actions
= repo
.get_actions()
464 return self
.render_string("modules/repo-actions-table.html",
465 repo
=repo
, actions
=actions
)
468 class UpdatesTableModule(UIModule
):
469 def render(self
, updates
):
470 return self
.render_string("modules/updates-table.html", updates
=updates
)
473 class WatchersSidebarTableModule(UIModule
):
475 return "css/watchers-sidebar-table.css"
477 def render(self
, build
, watchers
, limit
=5):
478 # Sort the watchers by their realname.
479 watchers
.sort(key
=lambda watcher
: watcher
.realname
)
481 return self
.render_string("modules/watchers-sidebar-table.html",
482 build
=build
, watchers
=watchers
, limit
=limit
)
485 class SelectLocaleModule(UIModule
):
487 # local code, English name, name
488 ("ca_ES", u
"Catalan", "Catal\xc3\xa0"),
489 ("da_DK", u
"Danish", u
"Dansk"),
490 ("de_DE", u
"German", u
"Deutsch"),
491 ("en_GB", u
"English (UK)", u
"English (UK)"),
492 ("en_US", u
"English (US)", u
"English (US)"),
493 ("es_ES", u
"Spanish (Spain)", u
"Espa\xf1ol (Espa\xf1a)"),
494 ("es_LA", u
"Spanish", u
"Espa\xf1ol"),
495 ("fr_CA", u
"French (Canada)", u
"Fran\xe7ais (Canada)"),
496 ("fr_FR", u
"French", u
"Fran\xe7ais"),
497 ("it_IT", u
"Italian", u
"Italiano"),
498 ("km_KH", u
"Khmer", u
"\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"),
499 ("nl_NL", u
"Dutch", u
"Nederlands"),
500 ("pt_BR", u
"Portuguese (Brazil)", u
"Portugu\xeas (Brasil)"),
501 ("pt_PT", u
"Portuguese (Portugal)", u
"Portugu\xeas (Portugal)"),
502 ("ro_RO", u
"Romanian", u
"Rom\xe2n\u0103"),
503 ("ru_RU", u
"Russian", u
"\u0440\u0443\u0441\u0441\u043a\u0438\u0439"),
504 ("uk_UA", u
"Ukrainian", u
"\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"),
507 # Sort the list of locales by their English name.
508 LOCALE_NAMES
.sort(key
=lambda x
: x
[1])
510 def render(self
, name
=None, id=None, preselect
=None):
511 return self
.render_string("modules/select/locale.html",
512 name
=name
, id=id, preselect
=preselect
, supported_locales
=self
.LOCALE_NAMES
)
515 class SelectTimezoneModule(UIModule
):
516 def render(self
, name
=None, id=None, preselect
=None):
517 return self
.render_string("modules/select/timezone.html",
518 name
=name
, id=id, preselect
=preselect
,
519 supported_timezones
=pytz
.common_timezones
)