]>
git.ipfire.org Git - pbs.git/blob - src/web/ui_modules.py
3 from __future__
import division
12 from ..constants
import *
14 class UIModule(tornado
.web
.UIModule
):
17 return self
.handler
.application
.backend
20 class TextModule(UIModule
):
21 BUGZILLA_PATTERN
= re
.compile(r
"(?:bug\s?|#)(\d+)")
22 CVE_PATTERN
= re
.compile(r
"(?:CVE)[\s\-](\d{4}\-\d{4})")
24 LINK
= """<a href="%s" target="_blank" rel="noopener">%s</a>"""
26 def render(self
, text
):
27 # Handle empty messages
31 # Search for bug ids that need to be linked to bugzilla
32 text
= re
.sub(self
.BUGZILLA_PATTERN
, self
._bugzilla
_repl
, text
, re
.I|re
.U
)
34 # Search for CVE numbers and create hyperlinks.
35 text
= re
.sub(self
.CVE_PATTERN
, self
._cve
_repl
, text
, re
.I|re
.U
)
37 return self
.render_string("modules/text.html", paragraphs
=text
.split("\n\n"))
39 def _bugzilla_repl(self
, m
):
43 bug_url
= self
.backend
.bugzilla
.bug_url(bug_id
)
45 return self
.LINK
% (bug_url
, m
.group(0))
47 def _cve_repl(self
, m
):
48 return self
.LINK
% ("http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s" % m
.group(1), m
.group(0))
51 class CommitMessageModule(UIModule
):
52 def render(self
, commit
):
53 return self
.render_string("modules/commit-message.html", commit
=commit
)
56 class ModalModule(UIModule
):
57 def render(self
, what
, **kwargs
):
58 what
= "modules/modal-%s.html" % what
60 return self
.render_string(what
, **kwargs
)
63 class BuildHeadlineModule(UIModule
):
64 def render(self
, build
, short
=False, shorter
=False):
68 return self
.render_string("modules/build-headline.html",
69 build
=build
, pkg
=build
.pkg
, short
=short
, shorter
=shorter
)
72 class JobsStatusModule(UIModule
):
73 def render(self
, build
):
74 return self
.render_string("modules/jobs/status.html",
75 build
=build
, jobs
=build
.jobs
)
78 class BugsTableModule(UIModule
):
79 def render(self
, pkg
, bugs
):
80 return self
.render_string("modules/bugs-table.html",
84 class ChangelogModule(UIModule
):
85 def render(self
, name
=None, builds
=None, *args
, **kwargs
):
87 builds
= self
.backend
.builds
.get_changelog(name
, *args
, **kwargs
)
89 return self
.render_string("modules/changelog/index.html", builds
=builds
)
92 class ChangelogEntryModule(UIModule
):
93 def render(self
, build
):
94 return self
.render_string("modules/changelog/entry.html", build
=build
)
97 class CommitsTableModule(UIModule
):
98 def render(self
, distro
, source
, commits
, full_format
=True):
99 return self
.render_string("modules/commits-table.html",
100 distro
=distro
, source
=source
, commits
=commits
,
101 full_format
=full_format
)
104 class FooterModule(UIModule
):
106 return self
.render_string("modules/footer.html")
109 class HeadingDateModule(UIModule
):
110 def render(self
, date
):
111 _
= self
.locale
.translate
113 # Check if this is today.
114 today
= datetime
.date
.today()
118 # Check if this was yesterday.
119 yesterday
= today
- datetime
.timedelta(days
=1)
120 if date
== yesterday
:
121 return _("Yesterday")
123 # Convert date to datetime.
124 date
= datetime
.datetime(date
.year
, date
.month
, date
.day
)
126 return self
.locale
.format_date(date
, shorter
=True, relative
=False)
129 class PackagesTableModule(UIModule
):
130 def render(self
, job
, packages
):
131 return self
.render_string("modules/packages-table.html", job
=job
,
135 class PackagesDependencyTableModule(UIModule
):
136 def render(self
, pkg
):
137 if pkg
.type == "source":
139 (None, pkg
.requires
),
143 ("provides", pkg
.provides
),
144 ("requires", pkg
.requires
),
145 ("prerequires", pkg
.prerequires
),
146 ("conflicts", pkg
.conflicts
),
147 ("obsoletes", pkg
.obsoletes
),
148 ("recommends", pkg
.recommends
),
149 ("suggests", pkg
.suggests
),
153 for name
, deps
in all_deps
:
155 has_deps
.append((name
, deps
))
158 span
= math
.floor(12 / len(has_deps
))
165 return self
.render_string("modules/packages/dependency-table.html",
166 pkg
=pkg
, dependencies
=has_deps
, span
=span
)
169 class PackageTable2Module(UIModule
):
170 def render(self
, packages
):
171 return self
.render_string("modules/package-table-detail.html",
175 class FilesTableModule(UIModule
):
176 def render(self
, files
):
177 return self
.render_string("modules/files-table.html", files
=files
)
180 class LogFilesTableModule(UIModule
):
181 def render(self
, job
, files
):
182 return self
.render_string("modules/log-files-table.html", job
=job
,
186 class PackageHeaderModule(UIModule
):
187 def render(self
, pkg
):
188 return self
.render_string("modules/package-header.html", pkg
=pkg
)
191 class PackageFilesTableModule(UIModule
):
192 def render(self
, pkg
, filelist
):
193 return self
.render_string("modules/packages-files-table.html",
194 pkg
=pkg
, filelist
=filelist
)
197 class BuildTableModule(UIModule
):
198 def render(self
, builds
, **kwargs
):
202 show_repo_time
= False,
203 show_can_move_forward
= False,
206 settings
.update(kwargs
)
212 dates
[b
.date
].append(b
)
216 dates
= sorted(dates
.items(), reverse
=True)
218 return self
.render_string("modules/build-table.html", dates
=dates
, **settings
)
221 class BuildStateWarningsModule(UIModule
):
222 def render(self
, build
):
223 return self
.render_string("modules/build-state-warnings.html", build
=build
)
225 class BuildState(UIModule
):
226 def render(self
, build_type
, build_state
):
227 if build_type
== "release" and build_state
== "stable":
228 return """text-success"""
229 elif build_type
== "release" and build_state
== "unstable":
230 return """text-danger"""
231 elif build_type
== "release" and build_state
== "testing":
232 return """text-warning"""
233 elif build_type
== "release" and build_state
== "obsolete":
234 return """text-muted"""
235 elif build_type
== "scratch" and build_state
== "stable":
236 return """text-success font-italic"""
237 elif build_type
== "scratch" and build_state
== "unstable":
238 return """text-danger font-italic"""
239 elif build_type
== "scratch" and build_state
== "testing":
240 return """text-warning font-italic"""
241 elif build_type
== "scratch" and build_state
== "obsolete":
242 return """text-muted font-italic"""
245 class JobsBoxesModule(UIModule
):
246 def render(self
, build
, jobs
=None):
250 return self
.render_string("modules/jobs/boxes.html",
251 build
=build
, jobs
=jobs
)
254 class JobStateModule(UIModule
):
255 def render(self
, job
, cls
=None, show_arch
=False, show_icon
=False, plain
=False):
258 _
= self
.locale
.translate
262 if state
== "aborted":
264 classes
.append("muted")
265 icon
= "icon-warning-sign"
267 elif state
== "dispatching":
268 text
= _("Dispatching")
269 classes
.append("text-info")
270 icon
= "icon-download-alt"
272 elif state
== "failed":
274 classes
.append("text-error")
277 elif state
== "finished":
279 classes
.append("text-success")
282 elif state
== "pending":
284 classes
.append("muted")
287 elif state
== "running":
289 classes
.append("text-info")
292 elif state
== "uploading":
293 text
= _("Uploading")
294 classes
.append("text-info")
295 icon
= "icon-upload-alt"
297 # Return just the string, is state is unknown.
299 text
= _("Unknown: %s") % state
300 classes
.append("muted")
311 if show_icon
and icon
:
312 text
= """<i class="%s"></i> %s""" % (icon
, text
)
314 return """<span class="%s">%s</span>""" % (" ".join(classes
), text
)
317 class JobsTableModule(UIModule
):
318 def render(self
, build
, jobs
=None, type="release"):
322 return self
.render_string("modules/jobs-table.html", build
=build
,
323 jobs
=jobs
, type=type)
326 class JobsListModule(UIModule
):
327 def render(self
, jobs
):
328 return self
.render_string("modules/jobs/list.html", jobs
=jobs
)
331 class RepositoryTableModule(UIModule
):
332 def render(self
, distro
, repos
):
333 return self
.render_string("modules/repository-table.html",
334 distro
=distro
, repos
=repos
)
337 class SourceTableModule(UIModule
):
338 def render(self
, distro
, sources
):
339 return self
.render_string("modules/source-table.html",
340 distro
=distro
, sources
=sources
)
343 class CommentsTableModule(UIModule
):
344 def render(self
, comments
, show_package
=False, show_user
=True):
346 for comment
in comments
:
349 pkg
= pkgs
[comment
.pkg_id
]
351 pkg
= pkgs
[comment
.pkg_id
] = \
352 self
.backend
.packages
.get_by_id(comment
.pkg_id
)
358 user
= users
[comment
.user_id
]
360 user
= users
[comment
.user_id
] = \
361 self
.backend
.users
.get_by_id(comment
.user_id
)
363 comment
["user"] = user
365 return self
.render_string("modules/comments-table.html",
366 comments
=comments
, show_package
=show_package
, show_user
=show_user
)
369 class LogModule(UIModule
):
370 def render(self
, entries
, **args
):
371 return self
.render_string("modules/log.html",
372 entries
=entries
, args
=args
)
375 class LogEntryModule(UIModule
):
376 def render(self
, entry
, small
=None, **args
):
377 if small
or not entry
.user
:
378 template
= "modules/log-entry-small.html"
380 template
= "modules/log-entry.html"
382 return self
.render_string(template
, entry
=entry
, u
=entry
.user
,
383 show_build
=False, **args
)
386 class LogEntryCommentModule(LogEntryModule
):
387 def render(self
, entry
, show_build
=False, **args
):
388 return self
.render_string("modules/log-entry-comment.html",
389 entry
=entry
, u
=entry
.user
, show_build
=show_build
, **args
)
392 class LinkToUserModule(UIModule
):
393 def render(self
, user
):
394 return self
.render_string("modules/link-to-user.html", user
=user
, users
=users
)
397 class BuildLogModule(UIModule
):
399 def render(self
, messages
):
400 _
= self
.locale
.translate
402 for message
in messages
:
404 msg
= LOG2MSG
[message
.message
]
405 message
["message"] = _(msg
)
409 return self
.render_string("modules/build-log.html", messages
=messages
)
412 class LogTableModule(UIModule
):
413 def render(self
, messages
, links
=["pkg",]):
414 for message
in messages
:
416 message
["message"] = LOG2MSG
[message
.message
]
421 message
["build"] = self
.backend
.builds
.get_by_id(message
.build_id
)
424 message
["pkg"] = self
.backend
.packages
.get_by_id(message
.pkg_id
)
426 return self
.render_string("modules/log-table.html",
427 messages
=messages
, links
=links
)
430 class UsersTableModule(UIModule
):
431 def render(self
, users
):
432 return self
.render_string("modules/user-table.html", users
=users
)
435 class BuildOffsetModule(UIModule
):
437 return self
.render_string("modules/build-offset.html")
440 class RepoActionsTableModule(UIModule
):
441 def render(self
, repo
):
442 actions
= repo
.get_actions()
444 return self
.render_string("modules/repo-actions-table.html",
445 repo
=repo
, actions
=actions
)
448 class UpdatesTableModule(UIModule
):
449 def render(self
, updates
):
450 return self
.render_string("modules/updates-table.html", updates
=updates
)
453 class WatchersSidebarTableModule(UIModule
):
455 return "css/watchers-sidebar-table.css"
457 def render(self
, build
, watchers
, limit
=5):
458 # Sort the watchers by their realname.
459 watchers
.sort(key
=lambda watcher
: watcher
.realname
)
461 return self
.render_string("modules/watchers-sidebar-table.html",
462 build
=build
, watchers
=watchers
, limit
=limit
)
465 class SelectLocaleModule(UIModule
):
467 # local code, English name, name
468 ("ca_ES", u
"Catalan", "Catal\xc3\xa0"),
469 ("da_DK", u
"Danish", u
"Dansk"),
470 ("de_DE", u
"German", u
"Deutsch"),
471 ("en_GB", u
"English (UK)", u
"English (UK)"),
472 ("en_US", u
"English (US)", u
"English (US)"),
473 ("es_ES", u
"Spanish (Spain)", u
"Espa\xf1ol (Espa\xf1a)"),
474 ("es_LA", u
"Spanish", u
"Espa\xf1ol"),
475 ("fr_CA", u
"French (Canada)", u
"Fran\xe7ais (Canada)"),
476 ("fr_FR", u
"French", u
"Fran\xe7ais"),
477 ("it_IT", u
"Italian", u
"Italiano"),
478 ("km_KH", u
"Khmer", u
"\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"),
479 ("nl_NL", u
"Dutch", u
"Nederlands"),
480 ("pt_BR", u
"Portuguese (Brazil)", u
"Portugu\xeas (Brasil)"),
481 ("pt_PT", u
"Portuguese (Portugal)", u
"Portugu\xeas (Portugal)"),
482 ("ro_RO", u
"Romanian", u
"Rom\xe2n\u0103"),
483 ("ru_RU", u
"Russian", u
"\u0440\u0443\u0441\u0441\u043a\u0438\u0439"),
484 ("uk_UA", u
"Ukrainian", u
"\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"),
487 # Sort the list of locales by their English name.
488 LOCALE_NAMES
.sort(key
=lambda x
: x
[1])
490 def render(self
, name
=None, id=None, preselect
=None):
491 return self
.render_string("modules/select/locale.html",
492 name
=name
, id=id, preselect
=preselect
, supported_locales
=self
.LOCALE_NAMES
)
495 class SelectTimezoneModule(UIModule
):
496 def render(self
, name
=None, id=None, preselect
=None):
497 return self
.render_string("modules/select/timezone.html",
498 name
=name
, id=id, preselect
=preselect
,
499 supported_timezones
=pytz
.common_timezones
)