class Builds(base.Object):
- def get_by_id(self, id):
- return Build(self.pakfire, id)
+ def get_by_id(self, id, data=None):
+ return Build(self.pakfire, id, data=data)
def get_by_uuid(self, uuid):
build = self.db.get("SELECT id FROM builds WHERE uuid = %s LIMIT 1", uuid)
return self.get_by_id(build.id)
def get_all(self, limit=50):
- query = "SELECT id FROM builds ORDER BY time_created DESC"
+ query = "SELECT * FROM builds ORDER BY time_created DESC"
if limit:
query += " LIMIT %d" % limit
- return [self.get_by_id(b.id) for b in self.db.query(query)]
+ return [self.get_by_id(b.id, b) for b in self.db.query(query)]
- def get_by_user_iter(self, user, type=None, public=None, order_by="name"):
+ def get_by_user(self, user, type=None, public=None):
args = []
conditions = []
elif public is False:
conditions.append("public = 'N'")
- query = "SELECT builds.id AS id FROM builds \
+ query = "SELECT builds.* AS id FROM builds \
JOIN packages ON builds.pkg_id = packages.id"
if conditions:
query += " WHERE %s" % " AND ".join(conditions)
- if order_by == "name":
- query += " ORDER BY packages.name ASC"
- elif order_by == "date":
- query += " ORDER BY builds.time_created DESC"
+ query += " ORDER BY builds.time_created DESC"
+ builds = []
for build in self.db.query(query, *args):
- yield Build(self.pakfire, build.id)
+ build = Build(self.pakfire, build.id, build)
+ builds.append(build)
+
+ return builds
def get_by_name(self, name, type=None, public=None, user=None):
args = [name,]
def created(self):
return self.data.time_created
+ @property
+ def date(self):
+ return self.created.date()
+
@property
def public(self):
"""
"""
return self.data.public == "Y"
+ @property
+ def size(self):
+ """
+ Returns the size on disk of this build.
+ """
+ s = 0
+
+ # Add the source package.
+ if self.pkg:
+ s += self.pkg.size
+
+ # Add all jobs.
+ s += sum((j.size for j in self.jobs))
+
+ return s
+
#@property
#def state(self):
# # Cache all states.
def name(self):
return "%s-%s.%s" % (self.pkg.name, self.pkg.friendly_version, self.arch.name)
+ @property
+ def size(self):
+ return sum((p.size for p in self.packages))
+
def get_state(self):
return self.data.state
window.prettyPrint && prettyPrint()
// Activate tooltips.
+ $("a[rel=tooltip]").tooltip();
$("span[rel=tooltip]").tooltip();
});
{% extends "base.html" %}
-{% block title %}{{ _("Build list") }}{% end block %}
+{% block title %}{{ _("Builds") }}{% end block %}
{% block body %}
- <h1>{{ _("Build list") }}</h1>
- {% module BuildTable(builds, show_user=True) %}
-{% end block %}
+ <div class="page-header">
+ <h2>{{ _("Builds") }}</h2>
+ </div>
-{% block sidebar %}
- <h1>{{ _("Actions") }}</h1>
- <ul>
- <li><a href="/builds/queue">{{ _("Job queue") }}</a></li>
- <li><a href="/builds/filter">{{ _("Filter builds") }}</a></li>
- </ul>
+ {% module BuildTable(builds, show_user=True) %}
{% end block %}
-{% if builds %}
+{% if dates %}
<table class="table table-striped table-hover">
- <thead>
- <tr>
- <th>{{ _("Build") }}</th>
- <th>{{ _("Jobs") }}</th>
- {% if show_repo %}
- <th>{{ _("Repository") }}</th>
- {% end %}
- {% if show_user %}
- <th>{{ _("User") }}</th>
- {% end %}
- {% if show_when %}
- <th>{{ _("When") }}</th>
- {% end %}
- </tr>
- </thead>
<tbody>
- {% for build in builds %}
- <tr class="build build_state_{{ build.state }}">
- <td class="name">
- <a class="build {{ build.type }} {{ build.state }} {% if build.is_broken() %}line-through{% end %}"
- href="/build/{{ build.uuid }}">{{ build.name }}</a>
+ {% for date, builds in dates %}
+ <tr>
+ <td colspan="4">
+ <h4>
+ {% module HeadingDate(date) %}
+ <small>({{ len(builds) }})</small>
+ </h4>
</td>
-
- <td class="jobs">
- {% if build.jobs %}
- {% for job in build.jobs %}
- <a class="job {{ job.state }}" title="{{ job.state }}"
- href="/job/{{ job.uuid }}">{{ job.arch.name }}</a>
- {% end %}
- {% else %}
- {{ _("This build has got no jobs.") }}
- {% end %}
- </td>
-
+ </tr>
+ <tr>
+ <th>{{ _("Build") }}</th>
+ <th>{{ _("Jobs") }}</th>
{% if show_repo %}
- <td>
- {% if build.repo %}
- <a href="/distro/{{ build.distro.identifier }}">{{ build.distro.name }}</a>
- /
- <a href="/distro/{{ build.distro.identifier }}/repo/{{ build.repo.identifier }}">{{ build.repo.name }}</a>
- {% else %}
-
- {% end %}
- </td>
+ <th>{{ _("Repository") }}</th>
{% end %}
-
{% if show_user %}
- {% if build.type == "scratch" and build.user %}
- <td class="user">
- {% module Maintainer(build.user) %}
- </td>
- {% elif build.type == "release" %}
- <td>{% module Maintainer(build.pkg.maintainer) %}</td>
- {% else %}
- <td> </td>
- {% end %}
+ <th>{{ _("User") }}</th>
{% end %}
-
{% if show_when %}
- <td>
- {{ format_date(build.created, relative=True) }}
- </td>
+ <th>{{ _("Created") }}</th>
{% end %}
+ </tr>
- {% if show_repo_time %}
- <td class="time">
- {{ format_date(build.repo_time, relative=False) }}
+ {% for build in builds %}
+ <tr>
+ <td class="name">
+ <a class="build {{ build.type }} {{ build.state }} {% if build.is_broken() %}line-through{% end %}"
+ href="/build/{{ build.uuid }}">{{ build.name }}</a>
</td>
- {% end %}
- {% if show_can_move_forward %}
- <td class="can-move-forward">
- {{ build.can_move_forward }}
+ <td>
+ {% module JobsStatus(build) %}
</td>
- {% end %}
- </tr>
+
+ {% if show_repo %}
+ <td>
+ {% if build.repo %}
+ <a href="/distro/{{ build.distro.identifier }}">{{ build.distro.name }}</a> /
+ <a href="/distro/{{ build.distro.identifier }}/repo/{{ build.repo.identifier }}">{{ build.repo.name }}</a>
+ {% end %}
+ </td>
+ {% end %}
+
+ {% if show_user %}
+ {% if build.type == "scratch" and build.user %}
+ <td>
+ {% module Maintainer(build.user) %}
+ </td>
+ {% elif build.type == "release" %}
+ <td>{% module Maintainer(build.pkg.maintainer) %}</td>
+ {% else %}
+ <td></td>
+ {% end %}
+ {% end %}
+
+ {% if show_when %}
+ <td>
+ {{ format_date(build.created, relative=True) }}
+ </td>
+ {% end %}
+
+ {% if show_repo_time %}
+ <td>
+ {{ format_date(build.repo_time, relative=False) }}
+ </td>
+ {% end %}
+
+ {% if show_can_move_forward %}
+ <td>
+ {{ build.can_move_forward }}
+ </td>
+ {% end %}
+ </tr>
+ {% end %}
{% end %}
</tbody>
</table>
{% else %}
- <div class="message message-warning">
- <span>{{ _("No builds") }}</span>
- {{ _("There are no builds to show at this place.") }}
- {{ _("Possibly you need to adjust your search.") }}
- </div>
+ <p class="muted ac">
+ {{ _("There are no builds to show at this place right now.") }}
+ </p>
{% end %}
--- /dev/null
+{% if jobs %}
+ {% for j in jobs %}
+ <a href="/job/{{ j.uuid }}" rel="tooltip" title="{% module JobState(j, plain=True) %}">
+ {% module JobState(j, show_arch=True) %}
+ </a>
+ {% end %}
+{% else %}
+ <span class="muted">
+ {{ _("This build has got no jobs.") }}
+ </span>
+{% end %}
<div class="lead lead-small ac">
{% module Text(pkg.description) %}
+ <br>
</div>
<div class="muted">
{% extends "base.html" %}
-{% block body %}
- <h1>{{ _("Builds by %s") % user.realname }}</h1>
-
- {% if builds %}
-
- {% for order, items in sorted(builds.items()) %}
- {{ order }}
+{% block title %}{{ _("Builds by %s") % user.realname }}{% end block %}
- {% module BuildTable(items) %}
- {% end %}
-
- {% else %}
-
- {{ _("No builds found matching your search criteria.") }}
+{% block body %}
+ <div class="page-header">
+ <h2>{{ _("Builds by %s") % user.realname }}</h2>
+ </div>
- {% end %}
+ {% module BuildTable(builds) %}
{% end block %}
# Jobs
"JobsList" : JobsListModule,
+ "JobsStatus" : JobsStatusModule,
# Packages
"PackagesDependencyTable" : PackagesDependencyTableModule,
"UsersTable" : UsersTableModule,
"WatchersSidebarTable" : WatchersSidebarTableModule,
+ "HeadingDate" : HeadingDateModule,
+
"SelectLocale" : SelectLocaleModule,
"SelectTimezone" : SelectTimezoneModule,
},
class BuildsHandler(BaseHandler):
def get(self):
- builds = self.pakfire.builds.get_all(limit=50)
+ limit = self.get_argument("limit", None)
+ try:
+ limit = int(limit)
+ except (TypeError, ValueError):
+ limit = 25
+
+ builds = self.pakfire.builds.get_all(limit=limit)
self.render("build-index.html", builds=builds)
class UsersBuildsHandler(BaseHandler):
- def __chunk_by_name(self, _builds):
- builds = {}
-
- for build in _builds:
- i = build.pkg.name[0]
- try:
- builds[i].append(build)
- except KeyError:
- builds[i] = [build,]
-
- return builds
- #return [v for k,v in sorted(builds.items())]
-
- def __chunk_by_date(self, _builds):
- # XXX dummy function
- builds = {
- datetime.datetime.utcnow() : _builds,
- }
-
- return builds
-
- for build in _builds:
- builds.append([build,])
-
- return builds
-
def get(self, name=None):
- if name:
+ if name is None:
+ user = self.current_user
+ else:
user = self.pakfire.users.get_by_name(name)
if not user:
raise tornado.web.HTTPError(404, "User not found: %s" % name)
- else:
- user = self.current_user
# By default users see only public builds.
# Admins are allowed to see all builds.
if self.current_user and self.current_user.is_admin():
public = None
- # Select the type of the builds that are shown.
- # None for all.
- type = self.get_argument("type", None)
-
- # Select how to order the results. The default is by date.
- order_by = self.get_argument("order_by", "date")
- if not order_by in ("date", "name"):
- order_by = "date"
-
# Get a list of the builds this user has built.
- builds = self.pakfire.builds.get_by_user_iter(user, type=type,
- public=public, order_by=order_by)
-
- if builds:
- # Chunk the list for a better presentation.
- if order_by == "date":
- builds = self.__chunk_by_date(builds)
- elif order_by == "name":
- builds = self.__chunk_by_name(builds)
+ builds = self.pakfire.builds.get_by_user(user, public=public)
self.render("user-profile-builds.html", user=user, builds=builds)
from __future__ import division
+import datetime
import math
import pytz
import re
prefix=prefix, build=build, pkg=build.pkg, short=short, shorter=shorter)
+class JobsStatusModule(UIModule):
+ def render(self, build):
+ return self.render_string("modules/jobs/status.html",
+ build=build, jobs=build.jobs)
+
+
class BuildersLoadModule(UIModule):
def render(self):
load = self.pakfire.builders.get_load()
return self.render_string("modules/footer.html")
+class HeadingDateModule(UIModule):
+ def render(self, date):
+ _ = self.locale.translate
+
+ # Check if this is today.
+ today = datetime.date.today()
+ if date == today:
+ return _("Today")
+
+ # Check if this was yesterday.
+ yesterday = today - datetime.timedelta(days=1)
+ if date == yesterday:
+ return _("Yesterday")
+
+ # Convert date to datetime.
+ date = datetime.datetime(date.year, date.month, date.day)
+
+ return self.locale.format_date(date, shorter=True, relative=False)
+
+
class PackagesTableModule(UIModule):
def render(self, job, packages):
return self.render_string("modules/packages-table.html", job=job,
)
settings.update(kwargs)
- return self.render_string("modules/build-table.html",
- builds=builds, **settings)
+ dates = {}
+
+ for b in builds:
+ try:
+ dates[b.date].append(b)
+ except KeyError:
+ dates[b.date] = [b,]
+
+ dates = sorted(dates.items(), reverse=True)
+
+ return self.render_string("modules/build-table.html", dates=dates, **settings)
class BuildStateWarningsModule(UIModule):
class JobStateModule(UIModule):
- def render(self, job, cls=None, show_icon=False):
+ def render(self, job, cls=None, show_arch=False, show_icon=False, plain=False):
state = job.state
_ = self.locale.translate
text = _("Unknown: %s") % state
classes.append("muted")
+ if plain:
+ return text
+
if cls:
classes.append(cls)
+ if show_arch:
+ text = job.arch.name
+
if show_icon and icon:
text = """<i class="%s"></i> %s""" % (icon, text)