mirror of
https://github.com/odoo/runbot.git
synced 2025-03-27 13:25:47 +07:00
[IMP] runbot: use custom layout and improve views
Runbot layout modifies the website/portal base layout to remove navbar, footer, overides some custom styles. A lot of assets are loaded but not used. The only real usefull elements are base assets (bootstrap, ...) and the login button. Migrating to the next version of odoo is usually painfull because some xpath may break, extra element added, or some style change may break the page, needing to add more and more xpath, css rules, ... for very little benefits. This cleanup creates a custom base layout for runbot independant from base odoo templates. Also add a breadcrumb, navigation arrow, and improve batch links
This commit is contained in:
parent
460e26bafc
commit
9a3c11b09f
@ -22,7 +22,7 @@
|
|||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'security/ir.rule.csv',
|
'security/ir.rule.csv',
|
||||||
|
|
||||||
'templates/assets.xml',
|
'templates/utils.xml',
|
||||||
'templates/badge.xml',
|
'templates/badge.xml',
|
||||||
'templates/batch.xml',
|
'templates/batch.xml',
|
||||||
'templates/branch.xml',
|
'templates/branch.xml',
|
||||||
@ -34,7 +34,6 @@
|
|||||||
'templates/frontend.xml',
|
'templates/frontend.xml',
|
||||||
'templates/git.xml',
|
'templates/git.xml',
|
||||||
'templates/nginx.xml',
|
'templates/nginx.xml',
|
||||||
'templates/utils.xml',
|
|
||||||
'templates/build_error.xml',
|
'templates/build_error.xml',
|
||||||
|
|
||||||
'views/branch_views.xml',
|
'views/branch_views.xml',
|
||||||
|
@ -53,6 +53,7 @@ def route(routes, **kw):
|
|||||||
response.qcontext['current_path'] = request.httprequest.full_path
|
response.qcontext['current_path'] = request.httprequest.full_path
|
||||||
response.qcontext['refresh'] = refresh
|
response.qcontext['refresh'] = refresh
|
||||||
response.qcontext['filter_mode'] = filter_mode
|
response.qcontext['filter_mode'] = filter_mode
|
||||||
|
response.qcontext['default_category'] = request.env['ir.model.data'].xmlid_to_res_id('runbot.default_category')
|
||||||
response.qcontext['qu'] = QueryURL('/runbot/%s' % (slug(project)), path_args=['search'], search=search, refresh=refresh)
|
response.qcontext['qu'] = QueryURL('/runbot/%s' % (slug(project)), path_args=['search'], search=search, refresh=refresh)
|
||||||
if 'title' not in response.qcontext:
|
if 'title' not in response.qcontext:
|
||||||
response.qcontext['title'] = 'Runbot %s' % project.name or ''
|
response.qcontext['title'] = 'Runbot %s' % project.name or ''
|
||||||
@ -271,23 +272,35 @@ class Runbot(Controller):
|
|||||||
elif operation == 'wakeup':
|
elif operation == 'wakeup':
|
||||||
build._wake_up()
|
build._wake_up()
|
||||||
|
|
||||||
return werkzeug.utils.redirect(build.build_url)
|
return str(build.id)
|
||||||
|
|
||||||
@route(['/runbot/build/<int:build_id>'], type='http', auth="public", website=True, sitemap=False)
|
@route([
|
||||||
def build(self, build_id, search=None, **post):
|
'/runbot/build/<int:build_id>',
|
||||||
|
'/runbot/batch/<int:from_batch>/build/<int:build_id>'
|
||||||
|
], type='http', auth="public", website=True, sitemap=False)
|
||||||
|
def build(self, build_id, search=None, from_batch=None, **post):
|
||||||
"""Events/Logs"""
|
"""Events/Logs"""
|
||||||
|
|
||||||
Build = request.env['runbot.build']
|
if from_batch:
|
||||||
|
from_batch = request.env['runbot.batch'].browse(int(from_batch))
|
||||||
|
from_batch = from_batch.with_context(batch=from_batch)
|
||||||
|
Build = request.env['runbot.build'].with_context(batch=from_batch)
|
||||||
|
|
||||||
build = Build.browse([build_id])[0]
|
build = Build.browse([build_id])[0]
|
||||||
if not build.exists():
|
if not build.exists():
|
||||||
return request.not_found()
|
return request.not_found()
|
||||||
|
siblings = (build.parent_id.children_ids if build.parent_id else from_batch.slot_ids.build_id if from_batch else build).sorted('id')
|
||||||
context = {
|
context = {
|
||||||
'build': build,
|
'build': build,
|
||||||
'default_category': request.env['ir.model.data'].xmlid_to_res_id('runbot.default_category'),
|
'from_batch': from_batch,
|
||||||
'project': build.params_id.trigger_id.project_id,
|
'project': build.params_id.trigger_id.project_id,
|
||||||
'title': 'Build %s' % build.id
|
'title': 'Build %s' % build.id,
|
||||||
|
'siblings': siblings,
|
||||||
|
# following logic is not the most efficient but good enough
|
||||||
|
'prev_ko': next((b for b in reversed(siblings) if b.id < build.id and b.global_result != 'ok'), Build),
|
||||||
|
'prev_bu': next((b for b in reversed(siblings) if b.id < build.id), Build),
|
||||||
|
'next_bu': next((b for b in siblings if b.id > build.id), Build),
|
||||||
|
'next_ko': next((b for b in siblings if b.id > build.id and b.global_result != 'ok'), Build),
|
||||||
}
|
}
|
||||||
return request.render("runbot.build", context)
|
return request.render("runbot.build", context)
|
||||||
|
|
||||||
@ -426,7 +439,6 @@ class Runbot(Controller):
|
|||||||
context = {
|
context = {
|
||||||
'build': build,
|
'build': build,
|
||||||
'build_stats': build_stats,
|
'build_stats': build_stats,
|
||||||
'default_category': request.env['ir.model.data'].xmlid_to_res_id('runbot.default_category'),
|
|
||||||
'project': build.params_id.trigger_id.project_id,
|
'project': build.params_id.trigger_id.project_id,
|
||||||
'title': 'Build %s statistics' % build.id
|
'title': 'Build %s statistics' % build.id
|
||||||
}
|
}
|
||||||
|
@ -16,16 +16,18 @@
|
|||||||
<field name="name">R&D</field>
|
<field name="name">R&D</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="runbot.bundle" id="runbot.bundle_master">
|
<data noupdate="1">
|
||||||
<field name="name">master</field>
|
<record model="runbot.bundle" id="runbot.bundle_master" >
|
||||||
<field name="is_base">True</field>
|
<field name="name">master</field>
|
||||||
<field name="project_id" ref="runbot.main_project"/>
|
<field name="is_base">True</field>
|
||||||
</record>
|
<field name="project_id" ref="runbot.main_project"/>
|
||||||
<record model="runbot.bundle" id="runbot.bundle_dummy">
|
</record>
|
||||||
<field name="name">Dummy</field>
|
<record model="runbot.bundle" id="runbot.bundle_dummy">
|
||||||
<field name="no_build">True</field>
|
<field name="name">Dummy</field>
|
||||||
<field name="project_id" ref="runbot.main_project"/>
|
<field name="no_build">True</field>
|
||||||
</record>
|
<field name="project_id" ref="runbot.main_project"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
|
||||||
<record model="ir.config_parameter" id="runbot.runbot_is_base_regex">
|
<record model="ir.config_parameter" id="runbot.runbot_is_base_regex">
|
||||||
<field name="key">runbot.runbot_is_base_regex</field>
|
<field name="key">runbot.runbot_is_base_regex</field>
|
||||||
|
@ -51,8 +51,7 @@ class Batch(models.Model):
|
|||||||
|
|
||||||
def _url(self):
|
def _url(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
runbot_domain = self.env['runbot.runbot']._domain()
|
return "/runbot/batch/%s" % self.id
|
||||||
return "http://%s/runbot/batch/%s" % (runbot_domain, self.id)
|
|
||||||
|
|
||||||
def _new_commit(self, branch, match_type='new'):
|
def _new_commit(self, branch, match_type='new'):
|
||||||
# if not the same hash for repo:
|
# if not the same hash for repo:
|
||||||
|
@ -142,6 +142,7 @@ class BuildResult(models.Model):
|
|||||||
|
|
||||||
description = fields.Char('Description', help='Informative description')
|
description = fields.Char('Description', help='Informative description')
|
||||||
md_description = fields.Char(compute='_compute_md_description', String='MD Parsed Description', help='Informative description markdown parsed')
|
md_description = fields.Char(compute='_compute_md_description', String='MD Parsed Description', help='Informative description markdown parsed')
|
||||||
|
display_name = fields.Char(compute='_compute_display_name')
|
||||||
|
|
||||||
# Related fields for convenience
|
# Related fields for convenience
|
||||||
version_id = fields.Many2one('runbot.version', related='params_id.version_id', store=True, index=True)
|
version_id = fields.Many2one('runbot.version', related='params_id.version_id', store=True, index=True)
|
||||||
@ -201,6 +202,7 @@ class BuildResult(models.Model):
|
|||||||
parent_id = fields.Many2one('runbot.build', 'Parent Build', index=True)
|
parent_id = fields.Many2one('runbot.build', 'Parent Build', index=True)
|
||||||
parent_path = fields.Char('Parent path', index=True)
|
parent_path = fields.Char('Parent path', index=True)
|
||||||
top_parent = fields.Many2one('runbot.build', compute='_compute_top_parent')
|
top_parent = fields.Many2one('runbot.build', compute='_compute_top_parent')
|
||||||
|
ancestors = fields.Many2many('runbot.build', compute='_compute_ancestors')
|
||||||
# should we add a has children stored boolean?
|
# should we add a has children stored boolean?
|
||||||
children_ids = fields.One2many('runbot.build', 'parent_id')
|
children_ids = fields.One2many('runbot.build', 'parent_id')
|
||||||
|
|
||||||
@ -220,6 +222,11 @@ class BuildResult(models.Model):
|
|||||||
|
|
||||||
static_run = fields.Char('Static run URL')
|
static_run = fields.Char('Static run URL')
|
||||||
|
|
||||||
|
@api.depends('description', 'params_id.config_id')
|
||||||
|
def _compute_display_name(self):
|
||||||
|
for build in self:
|
||||||
|
build.display_name = build.description or build.config_id.name
|
||||||
|
|
||||||
@api.depends('params_id.config_id')
|
@api.depends('params_id.config_id')
|
||||||
def _compute_log_list(self): # storing this field because it will be access trhoug repo viewn and keep track of the list at create
|
def _compute_log_list(self): # storing this field because it will be access trhoug repo viewn and keep track of the list at create
|
||||||
for build in self:
|
for build in self:
|
||||||
@ -260,6 +267,10 @@ class BuildResult(models.Model):
|
|||||||
for build in self:
|
for build in self:
|
||||||
build.top_parent = self.browse(int(build.parent_path.split('/')[0]))
|
build.top_parent = self.browse(int(build.parent_path.split('/')[0]))
|
||||||
|
|
||||||
|
def _compute_ancestors(self):
|
||||||
|
for build in self:
|
||||||
|
build.ancestors = self.browse([int(b) for b in build.parent_path.split('/') if b])
|
||||||
|
|
||||||
def _get_youngest_state(self, states):
|
def _get_youngest_state(self, states):
|
||||||
index = min([self._get_state_score(state) for state in states])
|
index = min([self._get_state_score(state) for state in states])
|
||||||
return state_order[index]
|
return state_order[index]
|
||||||
@ -379,9 +390,15 @@ class BuildResult(models.Model):
|
|||||||
else:
|
else:
|
||||||
build.domain = "%s:%s" % (domain, build.port)
|
build.domain = "%s:%s" % (domain, build.port)
|
||||||
|
|
||||||
|
@api.depends_context('batch')
|
||||||
def _compute_build_url(self):
|
def _compute_build_url(self):
|
||||||
|
batch = self.env.context.get('batch')
|
||||||
|
print(self.env.context)
|
||||||
for build in self:
|
for build in self:
|
||||||
build.build_url = "/runbot/build/%s" % build.id
|
if batch:
|
||||||
|
build.build_url = "/runbot/batch/%s/build/%s" % (batch.id, build.id)
|
||||||
|
else:
|
||||||
|
build.build_url = "/runbot/build/%s" % build.id
|
||||||
|
|
||||||
@api.depends('job_start', 'job_end')
|
@api.depends('job_start', 'job_end')
|
||||||
def _compute_job_time(self):
|
def _compute_job_time(self):
|
||||||
|
@ -184,6 +184,11 @@ class Bundle(models.Model):
|
|||||||
for batch in batchs:
|
for batch in batchs:
|
||||||
batch.bundle_id.last_done_batch = batch
|
batch.bundle_id.last_done_batch = batch
|
||||||
|
|
||||||
|
def _url(self):
|
||||||
|
self.ensure_one()
|
||||||
|
return "/runbot/bundle/%s" % self.id
|
||||||
|
|
||||||
|
|
||||||
def create(self, values_list):
|
def create(self, values_list):
|
||||||
res = super().create(values_list)
|
res = super().create(values_list)
|
||||||
if res.is_base:
|
if res.is_base:
|
||||||
|
@ -146,7 +146,7 @@ class Runbot(models.AbstractModel):
|
|||||||
return self.env.cr.fetchall()
|
return self.env.cr.fetchall()
|
||||||
|
|
||||||
def _domain(self):
|
def _domain(self):
|
||||||
return self.env.get('ir.config_parameter').get_param('runbot.runbot_domain', fqdn())
|
return self.env.get('ir.config_parameter').sudo().get_param('runbot.runbot_domain', fqdn())
|
||||||
|
|
||||||
def _reload_nginx(self):
|
def _reload_nginx(self):
|
||||||
env = self.env
|
env = self.env
|
||||||
|
323
runbot/static/src/css/runbot.css
Normal file
323
runbot/static/src/css/runbot.css
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #212529;
|
||||||
|
text-align: left;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
line-height: inherit; /* reset fa icon line height to body height*/
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #00A09D;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #005452;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.breadcrumb-item.active a {
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
background-color: inherit;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build_details {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
border-top: 2px solid #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-toggle="collapse"] .fa:before {
|
||||||
|
content: "\f139";
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-toggle="collapse"].collapsed .fa:before {
|
||||||
|
content: "\f13a";
|
||||||
|
}
|
||||||
|
|
||||||
|
body, .table {
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-default {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #444;
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-default:hover {
|
||||||
|
background-color: #ccc;
|
||||||
|
color: #444;
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sm, .btn-group-sm > .btn {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
font-size: 0.89rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-ssm, .btn-group-ssm > .btn {
|
||||||
|
padding: 0.22rem 0.4rem;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
line-height: 1;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.killed, .bg-killed, .bg-killed-light {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-toggle:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.one_line {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_tile {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.branch_time {
|
||||||
|
float: right;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--info-light: #d9edf7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-success-light {
|
||||||
|
background-color: #dff0d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-danger-light {
|
||||||
|
background-color: #f2dede;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-info-light {
|
||||||
|
background-color: var(--info-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-warning-light {
|
||||||
|
background-color: #fff9e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-info {
|
||||||
|
color: #096b72 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build_subject_buttons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build_buttons {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-killed {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-killed {
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-condensed td {
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-through {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-light {
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slot_button_group {
|
||||||
|
display: flex;
|
||||||
|
padding: 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slot_button_group .btn {
|
||||||
|
flex: 0 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slot_button_group .btn.slot_name {
|
||||||
|
width: 40px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_header {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_header:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_hover {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_header:hover .header_hover {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_slots {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_commits {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_commits {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.match_type_new {
|
||||||
|
background-color: var(--info-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_row .slot_container {
|
||||||
|
flex: 1 0 200px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch_row .slot_filler {
|
||||||
|
width: 100px;
|
||||||
|
height: 0px;
|
||||||
|
flex: 1 0 200px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row {
|
||||||
|
border-bottom: 1px solid var(--gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row .batch_commits {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row .slot_container {
|
||||||
|
flex: 1 0 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row .slot_filler {
|
||||||
|
flex: 1 0 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row .more .batch_commits {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*.bundle_row .nomore .batch_commits {
|
||||||
|
display: none;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle_row .nomore.batch_tile:hover .batch_commits {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1px;
|
||||||
|
transform: translateY(100%);
|
||||||
|
z-index: 100;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.125);
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-left: -1px;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
.chart-legend {
|
||||||
|
max-height: calc(100vh - 160px);
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-legend .label {
|
||||||
|
margin-left: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-legend .disabled .color {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-legend .disabled .label {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: line-through;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-legend ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-height {
|
||||||
|
max-height: 180px;
|
||||||
|
overflow: scroll;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-height > hr {
|
||||||
|
margin: 2px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-height:before {
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(transparent 0px, white 27px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-height::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.limited-height-toggle:hover {
|
||||||
|
background-color: #DDD;
|
||||||
|
}
|
||||||
|
|
@ -1,255 +0,0 @@
|
|||||||
.separator {
|
|
||||||
border-top: 2px solid #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-toggle="collapse"] .fa:before {
|
|
||||||
content: "\f139";
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-toggle="collapse"].collapsed .fa:before {
|
|
||||||
content: "\f13a";
|
|
||||||
}
|
|
||||||
|
|
||||||
body, .table{
|
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
color:#444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-default {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #444;
|
|
||||||
border-color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-default:hover {
|
|
||||||
background-color: #ccc;
|
|
||||||
color: #444;
|
|
||||||
border-color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-sm, .btn-group-sm > .btn {
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
font-size: 0.89rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
}
|
|
||||||
.btn-ssm, .btn-group-ssm > .btn {
|
|
||||||
padding: 0.22rem 0.4rem;
|
|
||||||
font-size: 0.82rem;
|
|
||||||
line-height: 1;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.killed, .bg-killed, .bg-killed-light {
|
|
||||||
background-color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-toggle:after { content: none }
|
|
||||||
|
|
||||||
.one_line {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
.batch_tile {
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
.branch_time {
|
|
||||||
float:right;
|
|
||||||
margin-left:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--info-light: #d9edf7;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.bg-success-light {
|
|
||||||
background-color: #dff0d8;
|
|
||||||
}
|
|
||||||
.bg-danger-light {
|
|
||||||
background-color: #f2dede;
|
|
||||||
}
|
|
||||||
.bg-info-light {
|
|
||||||
background-color: var(--info-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-info{
|
|
||||||
color: #096b72 !important;
|
|
||||||
}
|
|
||||||
.build_subject_buttons {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.build_buttons {
|
|
||||||
margin-left: auto
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-killed {
|
|
||||||
background-color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-killed {
|
|
||||||
background-color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-condensed td {
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-through {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-light{
|
|
||||||
border: 1px solid #AAA;
|
|
||||||
}
|
|
||||||
.arrow{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-light:hover .arrow{
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slot_button_group {
|
|
||||||
display: flex;
|
|
||||||
padding: 0 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slot_button_group .btn {
|
|
||||||
flex: 0 0 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slot_button_group .btn.slot_name {
|
|
||||||
width: 40px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch_header {
|
|
||||||
padding: 6px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch_slots {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch_commits {
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch_commits {
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.match_type_new {
|
|
||||||
background-color: var(--info-light);
|
|
||||||
}
|
|
||||||
.batch_row {
|
|
||||||
.slot_container{
|
|
||||||
flex: 1 0 200px;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
.slot_filler {
|
|
||||||
width: 100px;
|
|
||||||
height: 0px;
|
|
||||||
flex: 1 0 200px;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.bundle_row {
|
|
||||||
border-bottom: 1px solid var(--gray);
|
|
||||||
.batch_commits {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
.slot_container{
|
|
||||||
flex:1 0 50%;
|
|
||||||
}
|
|
||||||
.slot_filler {
|
|
||||||
flex:1 0 50%;
|
|
||||||
}
|
|
||||||
.more {
|
|
||||||
.batch_commits {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.nomore {
|
|
||||||
.batch_commits {
|
|
||||||
display: none;
|
|
||||||
padding:8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.nomore.batch_tile:hover {
|
|
||||||
.batch_commits {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1px;
|
|
||||||
transform: translateY(100%);
|
|
||||||
z-index: 100;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.125);
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-left:-1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.chart-legend {
|
|
||||||
max-height: calc(100vh - 160px);
|
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
margin-left: 5px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.disabled{
|
|
||||||
.color {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
.label {
|
|
||||||
font-weight: normal;
|
|
||||||
text-decoration: line-through;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.limited-height {
|
|
||||||
max-height: 180px;
|
|
||||||
overflow: scroll;
|
|
||||||
|
|
||||||
>hr {
|
|
||||||
margin: 2px 0px;
|
|
||||||
}
|
|
||||||
&:before {
|
|
||||||
content:'';
|
|
||||||
width:100%;
|
|
||||||
height:30px;
|
|
||||||
position:absolute;
|
|
||||||
left:0;
|
|
||||||
bottom:0;
|
|
||||||
background:linear-gradient(transparent 0px, white 27px);
|
|
||||||
}
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
.limited-height::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.limited-height-toggle:hover {
|
|
||||||
background-color: #DDD;
|
|
||||||
}
|
|
@ -1,52 +1,32 @@
|
|||||||
(function($) {
|
(function($) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var OPMAP = {
|
|
||||||
'rebuild': {operation: 'rebuild', then: 'redirect'},
|
|
||||||
'kill': {operation: 'kill', then: 'reload'},
|
|
||||||
'wakeup': {operation: 'wakeup', then: 'reload'}
|
|
||||||
};
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
$(document).on('click', '[data-runbot]', function (e) {
|
$(document).on('click', '[data-runbot]', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var data = $(this).data();
|
var data = $(this).data();
|
||||||
var segment = OPMAP[data.runbot];
|
var operation = data.runbot;
|
||||||
if (!segment) { return; }
|
if (!operation) {
|
||||||
|
return;
|
||||||
// window.location.pathname but compatibility is iffy
|
}
|
||||||
var currentPath = window.location.href.replace(window.location.protocol + '//' + window.location.host, '').split('?')[0];
|
|
||||||
var buildPath = _.str.sprintf('/runbot/build/%s', data.runbotBuild);
|
|
||||||
// no responseURL on $.ajax so use native object
|
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.addEventListener('load', function () {
|
xhr.addEventListener('load', function () {
|
||||||
switch (segment.then) {
|
if (operation == 'rebuild' && window.location.href.split('?')[0].endsWith('/build/' + data.runbotBuild)){
|
||||||
case 'redirect':
|
window.location.href = window.location.href.replace('/build/' + data.runbotBuild, '/build/' + xhr.responseText);
|
||||||
if (currentPath === buildPath && xhr.responseURL) {
|
} else {
|
||||||
window.location.href = xhr.responseURL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// fallthrough to reload if no responseURL or we're
|
|
||||||
// not on the build's page
|
|
||||||
case 'reload':
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
xhr.open('POST', _.str.sprintf('%s/%s', buildPath, segment.operation));
|
xhr.open('POST', '/runbot/build/' + data.runbotBuild + '/' + operation);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
//$(function() {
|
|
||||||
// new Clipboard('.clipbtn');
|
|
||||||
//});
|
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|
||||||
|
|
||||||
function copyToClipboard(text) {
|
function copyToClipboard(text) {
|
||||||
if (!navigator.clipboard) {
|
if (!navigator.clipboard) {
|
||||||
console.error('Clipboard not supported');
|
console.error('Clipboard not supported');
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
navigator.clipboard.writeText(text);
|
|
||||||
}
|
}
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="runbot.assets.frontend">
|
|
||||||
<xpath expr="." position="inside">
|
|
||||||
<link rel="stylesheet" href="/runbot/static/src/css/runbot.scss"/>
|
|
||||||
<script type="text/javascript" src="/runbot/static/src/js/runbot.js"/>
|
|
||||||
<script type="text/javascript" src="/web/static/lib/Chart/Chart.js"></script>
|
|
||||||
</xpath>
|
|
||||||
</template>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.batch">
|
<template id="runbot.batch">
|
||||||
<t t-call="website.layout">
|
<t t-call="runbot.layout">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<table class="table table-stripped">
|
<table class="table table-stripped">
|
||||||
@ -14,18 +14,12 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr t-if="batch.category_id.id != default_category">
|
<tr t-if="batch.category_id.id != default_category">
|
||||||
<td>Category</td>
|
<td>Category</td>
|
||||||
<td t-esc="batch.category_id.name">
|
<td t-esc="batch.category_id.name"></td>
|
||||||
<i t-attf-class="fa fa-{{batch.category_id.name}}"/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Version</td>
|
<td>Version</td>
|
||||||
<td t-esc="batch.slot_ids[0].params_id.version_id.name if batch.slot_ids else batch.bundle_id.version_id.name"/>
|
<td t-esc="batch.slot_ids[0].params_id.version_id.name if batch.slot_ids else batch.bundle_id.version_id.name"/>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>State</td>
|
|
||||||
<td t-esc="batch.state"/>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Create date</td>
|
<td>Create date</td>
|
||||||
<td t-esc="batch.create_date"/>
|
<td t-esc="batch.create_date"/>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.branch">
|
<template id="runbot.branch">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class='col-md-12'>
|
<div class='col-md-12'>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.build">
|
<template id="runbot.build">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<t t-set="nav_form">
|
<t t-set="nav_form">
|
||||||
<form class="form-inline">
|
<form class="form-inline">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
@ -18,189 +18,206 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<t t-set="batches" t-value="build.top_parent.with_context(active_test=False).slot_ids.mapped('batch_id')"/>
|
<t t-set="batches" t-value="build.top_parent.with_context(active_test=False).slot_ids.mapped('batch_id')"/>
|
||||||
<t t-set="bundles" t-value="batches.mapped('bundle_id')"/>
|
<t t-set="bundles" t-value="batches.mapped('bundle_id')"/>
|
||||||
<t t-if="batches">
|
|
||||||
<t t-if="len(bundles) == 1">
|
<t t-if="from_batch" t-set="unique_batch" t-value="from_batch"/>
|
||||||
<t t-if="len(batches) == 1">
|
<t t-if="from_batch" t-set="unique_bundle" t-value="from_batch.bundle_id"/>
|
||||||
<b>Batch:</b>
|
<t t-if="not unique_batch and len(batches) == 1" t-set="unique_batch" t-value="batches"/>
|
||||||
<a t-esc="bundles.name" t-attf-href="/runbot/batch/{{batches[0].id}}"/>
|
<t t-if="not unique_bundle and len(bundles) == 1" t-set="unique_bundle" t-value="bundles"/>
|
||||||
</t>
|
|
||||||
<t t-else="">
|
<!-- Breadcrumbs & Previous/Next-->
|
||||||
<b>Bundle:</b>
|
<nav aria-label="breadcrumb" class="d-flex justify-content-between align-items-center">
|
||||||
<t t-esc="bundles.name" t-attf-href="/runbot/bundle/{{bundle.id}}"/>
|
<ol class="breadcrumb mb-0">
|
||||||
<br/>
|
<li t-attf-class="breadcrumb-item">
|
||||||
</t>
|
<a t-attf-href="/runbot/{{build.params_id.project_id.id}}">
|
||||||
</t>
|
<t t-esc="build.params_id.project_id.name"/>
|
||||||
<t t-else="">
|
</a>
|
||||||
This build is referenced in
|
</li>
|
||||||
<t t-esc="len(bundles)"/>
|
<li t-if="unique_bundle" t-attf-class="breadcrumb-item">
|
||||||
bundles
|
<a t-att-href="unique_bundle._url()">
|
||||||
<t t-if="more">
|
<t t-esc="unique_bundle.name"/>
|
||||||
:
|
</a>
|
||||||
<a t-foreach="bundles" class="badge badge-light" t-as="bundle" t-esc="bundle.name" t-attf-href="/runbot/bundle/{{bundle.id}}"/>
|
</li>
|
||||||
</t>
|
<li t-if="unique_batch" t-attf-class="breadcrumb-item">
|
||||||
<br/>
|
<a t-att-href="unique_batch._url()">
|
||||||
|
batch-<t t-esc="unique_batch.id"/> (<t t-esc="build.params_id.trigger_id.name"/>)
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li t-foreach="build.ancestors" t-as="ancestor" t-attf-class="breadcrumb-item{{' active' if ancestor == build else ''}}">
|
||||||
|
<a t-att-href="ancestor.build_url">
|
||||||
|
<t t-esc="ancestor.description or ancestor.config_id.name"/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<span class="btn-group pr-3">
|
||||||
|
<a t-att-href="prev_ko.build_url" role="button" t-attf-title="Previous ko {{prev_ko.display_name}}"
|
||||||
|
t-attf-class="{{'' if prev_ko else 'disabled '}}btn btn-default fa fa-angle-double-left"></a>
|
||||||
|
<a t-att-href="prev_bu.build_url" role="button" t-attf-title="Previous {{prev_bu.display_name}}"
|
||||||
|
t-attf-class="{{'' if prev_bu else 'disabled '}}btn btn-default fa fa-chevron-left"></a>
|
||||||
|
<a t-att-href="next_bu.build_url" role="button" t-attf-title="Next {{next_bu.display_name}}"
|
||||||
|
t-attf-class="{{'' if next_bu else 'disabled '}}btn btn-default fa fa-chevron-right"></a>
|
||||||
|
<a t-att-href="next_ko.build_url" role="button" t-attf-title="Next ko {{next_ko.display_name}}"
|
||||||
|
t-attf-class="{{'' if next_ko else 'disabled '}}btn btn-default fa fa-angle-double-right"></a>
|
||||||
|
</span>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<!-- Build details-->
|
||||||
|
<t t-set="rowclass">
|
||||||
|
<t t-call="runbot.build_class">
|
||||||
|
<t t-set="build" t-value="build"/>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<div t-attf-class="bg-{{rowclass.strip()}}-light {{'col-md-6' if build.children_ids else 'col-md-12'}}">
|
||||||
|
<div class="build_details">
|
||||||
|
<!-- Batch/bundles links-->
|
||||||
|
<t t-if="len(bundles) > 1">
|
||||||
|
This build is referenced in <t t-esc="len(bundles)"/> bundles
|
||||||
|
<ul>
|
||||||
|
<li t-foreach="bundles" t-as="bundle" ><a t-esc="bundle.name" t-attf-href="/runbot/bundle/{{bundle.id}}"/></li>
|
||||||
|
</ul>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="len(batches) > 1">
|
<t t-if="len(batches) > 1">
|
||||||
First apparition:
|
<b>First apparition:</b> <a t-esc="batches[0].bundle_id.name" t-attf-href="/runbot/batch/{{batches[0].id}}"/><br/>
|
||||||
<a t-esc="batches[0].bundle_id.name" t-attf-href="/runbot/batch/{{batches[0].id}}"/>
|
<b>Last apparition:</b> <a t-esc="batches[-1].bundle_id.name" t-attf-href="/runbot/batch/{{batches[-1].id}}"/><br/>
|
||||||
<br/>
|
|
||||||
Last apparition:
|
|
||||||
<a t-esc="batches[-1].bundle_id.name" t-attf-href="/runbot/batch/{{batches[-1].id}}"/>
|
|
||||||
<br/>
|
|
||||||
</t>
|
</t>
|
||||||
</t>
|
<!-- Parent -->
|
||||||
<div t-if="build.parent_id">
|
<div t-if="build.parent_id and build.orphan_result">
|
||||||
<b>Parent build:</b>
|
|
||||||
<a t-attf-href="/runbot/build/#{build.parent_id.id}">
|
|
||||||
<t t-esc="build.parent_id.dest"/>
|
|
||||||
</a>
|
|
||||||
<t t-if="build.orphan_result">
|
|
||||||
&nbsp;
|
|
||||||
<i class="fa fa-chain-broken" title="Build result ignored for parent" />
|
<i class="fa fa-chain-broken" title="Build result ignored for parent" />
|
||||||
&nbsp;Orphaned build, the result does not affect parent build result
|
&nbsp;Orphaned build, the result does not affect parent build result
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<t t-if="build.description">
|
||||||
|
<b>Description:</b>
|
||||||
|
<t t-raw="build.md_description"/>
|
||||||
|
<br/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<!-- Commits -->
|
||||||
|
<t t-foreach="build.params_id.sudo().commit_link_ids" t-as="build_commit">
|
||||||
|
<b>Commit:</b>
|
||||||
|
<a t-attf-href="/runbot/commit/{{build_commit.commit_id.id}}">
|
||||||
|
<t t-esc="build_commit.commit_id.dname"/>
|
||||||
|
</a>
|
||||||
|
&nbsp;
|
||||||
|
<a t-att-href="'https://%s/commit/%s' % (build_commit.branch_id.remote_id.base_url, build_commit.commit_id.name)" title="View Commit on Github"><i class="fa fa-github"/></a>
|
||||||
|
<t t-if="build_commit.match_type in ('default', 'pr_target', 'prefix') ">
|
||||||
|
from base branch
|
||||||
|
<br/>
|
||||||
|
</t>
|
||||||
|
<div t-else="" class="ml-3">
|
||||||
|
<b>Subject:</b>
|
||||||
|
<t t-esc="build_commit.commit_id.subject"/>
|
||||||
|
<br/>
|
||||||
|
<b>Author:</b>
|
||||||
|
<t t-esc="build_commit.commit_id.author"/>
|
||||||
|
<br/>
|
||||||
|
<b>Committer:</b>
|
||||||
|
<t t-esc="build_commit.commit_id.committer"/>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
<b>Version:</b>
|
||||||
|
<t t-esc="build.params_id.version_id.name"/>
|
||||||
|
<br/>
|
||||||
|
<b>Config:</b>
|
||||||
|
<t t-esc="build.params_id.config_id.name"/>
|
||||||
|
<br/>
|
||||||
|
<t t-if='more'>
|
||||||
|
<b>Trigger:</b>
|
||||||
|
<t t-esc="build.params_id.trigger_id.name"/>
|
||||||
|
<br/>
|
||||||
|
<b>Config data:</b>
|
||||||
|
<t t-esc="build.params_id.config_data.dict"/>
|
||||||
|
<br/>
|
||||||
|
<b>Modules:</b>
|
||||||
|
<t t-esc="build.params_id.modules"/>
|
||||||
|
<br/>
|
||||||
|
<b>Extra params:</b>
|
||||||
|
<t t-esc="build.params_id.extra_params"/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<t t-if="len(build.params_id.builds_reference_ids) > 1">
|
||||||
|
<b>Reference batch:</b>
|
||||||
|
<t t-foreach="build.params_id.builds_reference_ids" t-as="reference">
|
||||||
|
<span t-esc="reference.id"/>
|
||||||
|
</t>
|
||||||
|
<br/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-if="len(build.params_id.build_ids) > 1">
|
||||||
|
<b>Similar builds:</b>
|
||||||
|
<t t-foreach="build.params_id.build_ids" t-as="simbuild">
|
||||||
|
<a t-if="simbuild.id != build.id" t-attf-href="/runbot/build/#{simbuild.id}">
|
||||||
|
<span
|
||||||
|
t-attf-class="badge badge-{{simbuild.get_color_class()}}"
|
||||||
|
t-esc="simbuild.id"/>
|
||||||
|
</a>
|
||||||
|
</t>
|
||||||
|
<br/>
|
||||||
|
</t>
|
||||||
|
<b>Host:</b>
|
||||||
|
<t t-esc="build.host"/>
|
||||||
|
<br/>
|
||||||
|
</t>
|
||||||
|
<b>Total time:</b>
|
||||||
|
<t t-esc="build.get_formated_build_time()"/>
|
||||||
|
<br/>
|
||||||
|
<t t-if="build.stat_ids">
|
||||||
|
<b>Stats:</b>
|
||||||
|
<a t-attf-href="/runbot/build/stats/{{build.id}}">Build <t t-esc="build.id"/></a>
|
||||||
|
<br/>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-6" t-if="build.children_ids">
|
||||||
<table class="table table-condensed tabel-bordered">
|
Children:
|
||||||
<tr>
|
<table class="table table-condensed">
|
||||||
|
<t t-foreach="build.children_ids.sorted('id')" t-as="child">
|
||||||
<t t-set="rowclass">
|
<t t-set="rowclass">
|
||||||
<t t-call="runbot.build_class">
|
<t t-call="runbot.build_class">
|
||||||
<t t-set="build" t-value="build"/>
|
<t t-set="build" t-value="child"/>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<td t-attf-class="bg-{{rowclass.strip()}}-light">
|
<tr t-attf-class="bg-{{rowclass.strip()}}-light{{' line-through' if child.orphan_result else ''}}">
|
||||||
<t t-if="build.description">
|
<td>
|
||||||
<b>Description:</b>
|
<a t-attf-href="/runbot/{{'batch/%s/' % from_batch.id if from_batch else ''}}build/{{child.id}}">
|
||||||
<t t-raw="build.md_description"/>
|
Build
|
||||||
<br/>
|
<t t-esc="child.id"/>
|
||||||
</t>
|
|
||||||
<t t-foreach="build.params_id.sudo().commit_link_ids" t-as="build_commit">
|
|
||||||
<b>Commit:</b>
|
|
||||||
<a t-attf-href="/runbot/commit/{{build_commit.commit_id.id}}">
|
|
||||||
<t t-esc="build_commit.commit_id.dname"/>
|
|
||||||
</a>
|
</a>
|
||||||
<a t-att-href="'https://%s/commit/%s' % (build_commit.branch_id.remote_id.base_url, build_commit.commit_id.name)" class="btn btn-sm text-left" title="View Commit on Github"><i class="fa fa-github"/></a>
|
<t t-if="child.description">
|
||||||
<t t-if="build_commit.match_type in ('default', 'pr_target', 'prefix') ">
|
<t t-raw="child.md_description" />
|
||||||
from base branch
|
|
||||||
<br/>
|
|
||||||
</t>
|
</t>
|
||||||
<div t-else="" class="ml-3">
|
<t t-else="">
|
||||||
<b>Subject:</b>
|
with config
|
||||||
<t t-esc="build_commit.commit_id.subject"/>
|
<t t-esc="child.params_id.config_id.name"/>
|
||||||
<br/>
|
</t>
|
||||||
<b>Author:</b>
|
<a groups="runbot.group_build_config_user" t-attf-href="/web#id={{child.params_id.config_id.id}}&view_type=form&model=runbot.build.config">...</a>
|
||||||
<t t-esc="build_commit.commit_id.author"/>
|
<t t-if="child.orphan_result">
|
||||||
<br/>
|
<i class="fa fa-chain-broken" title="Build result ignored for parent" />
|
||||||
<b>Committer:</b>
|
</t>
|
||||||
<t t-esc="build_commit.commit_id.committer"/>
|
<t t-if="child.job">
|
||||||
<br/>
|
Running step:
|
||||||
</div>
|
<t t-esc="child.job"/>
|
||||||
</t>
|
</t>
|
||||||
<b>Version:</b>
|
<t t-if="child.global_state in ['testing', 'waiting']">
|
||||||
<t t-esc="build.params_id.version_id.name"/>
|
<i class="fa fa-spinner fa-spin"/>
|
||||||
<br/>
|
<t t-esc="child.global_state"/>
|
||||||
<b>Config:</b>
|
</t>
|
||||||
<t t-esc="build.params_id.config_id.name"/>
|
</td>
|
||||||
<br/>
|
<td>
|
||||||
<t t-if='more'>
|
<span t-attf-class="badge badge-info" t-esc="child.get_formated_build_time()"/>
|
||||||
<b>Trigger:</b>
|
</td>
|
||||||
<t t-esc="build.params_id.trigger_id.name"/>
|
<td>
|
||||||
<br/>
|
<t t-call="runbot.build_button">
|
||||||
<b>Config data:</b>
|
<t t-set="bu" t-value="child"/>
|
||||||
<t t-esc="build.params_id.config_data.dict"/>
|
<t t-set="klass" t-value="'btn-group-ssm'"/>
|
||||||
<br/>
|
|
||||||
<b>Modules:</b>
|
|
||||||
<t t-esc="build.params_id.modules"/>
|
|
||||||
<br/>
|
|
||||||
<b>Extra params:</b>
|
|
||||||
<t t-esc="build.params_id.extra_params"/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<t t-if="len(build.params_id.builds_reference_ids) > 1">
|
|
||||||
<b>Reference batch:</b>
|
|
||||||
<t t-foreach="build.params_id.builds_reference_ids" t-as="reference">
|
|
||||||
<span t-esc="reference.id"/>
|
|
||||||
</t>
|
|
||||||
<br/>
|
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
<t t-if="len(build.params_id.build_ids) > 1">
|
</td>
|
||||||
<b>Similar builds:</b>
|
</tr>
|
||||||
<t t-foreach="build.params_id.build_ids" t-as="simbuild">
|
</t>
|
||||||
<a t-if="simbuild.id != build.id" t-attf-href="/runbot/build/#{simbuild.id}">
|
|
||||||
<span
|
|
||||||
t-attf-class="badge badge-{{simbuild.get_color_class()}}"
|
|
||||||
t-esc="simbuild.id"/>
|
|
||||||
</a>
|
|
||||||
</t>
|
|
||||||
<br/>
|
|
||||||
</t>
|
|
||||||
<b>Host:</b>
|
|
||||||
<t t-esc="build.host"/>
|
|
||||||
<br/>
|
|
||||||
</t>
|
|
||||||
<b>Total time:</b>
|
|
||||||
<t t-esc="build.get_formated_build_time()"/>
|
|
||||||
<br/>
|
|
||||||
<t t-if="build.stat_ids">
|
|
||||||
<b>Stats:</b>
|
|
||||||
<a t-attf-href="/runbot/build/stats/{{build.id}}">Build <t t-esc="build.id"/></a>
|
|
||||||
<br/>
|
|
||||||
</t>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
<td t-if="build.children_ids">
|
|
||||||
Children:
|
|
||||||
<table class="table table-condensed">
|
|
||||||
<t t-foreach="build.children_ids.sorted('id')" t-as="child">
|
|
||||||
<t t-set="rowclass">
|
|
||||||
<t t-call="runbot.build_class">
|
|
||||||
<t t-set="build" t-value="child"/>
|
|
||||||
</t>
|
|
||||||
</t>
|
|
||||||
<tr t-attf-class="bg-{{rowclass.strip()}}-light{{' line-through' if child.orphan_result else ''}}">
|
|
||||||
<td>
|
|
||||||
<a t-attf-href="/runbot/build/{{child.id}}">
|
|
||||||
Build
|
|
||||||
<t t-esc="child.id"/>
|
|
||||||
</a>
|
|
||||||
<t t-if="child.description">
|
|
||||||
<t t-raw="child.md_description" />
|
|
||||||
</t>
|
|
||||||
<t t-else="">
|
|
||||||
with config
|
|
||||||
<t t-esc="child.params_id.config_id.name"/>
|
|
||||||
</t>
|
|
||||||
<a groups="runbot.group_build_config_user" t-attf-href="/web#id={{child.params_id.config_id.id}}&view_type=form&model=runbot.build.config">...</a>
|
|
||||||
<t t-if="child.orphan_result">
|
|
||||||
<i class="fa fa-chain-broken" title="Build result ignored for parent" />
|
|
||||||
</t>
|
|
||||||
<t t-if="child.job">
|
|
||||||
Running step:
|
|
||||||
<t t-esc="child.job"/>
|
|
||||||
</t>
|
|
||||||
<t t-if="child.global_state in ['testing', 'waiting']">
|
|
||||||
<i class="fa fa-spinner fa-spin"/>
|
|
||||||
<t t-esc="child.global_state"/>
|
|
||||||
</t>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span t-attf-class="badge badge-info" t-esc="child.get_formated_build_time()"/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<t t-call="runbot.build_button">
|
|
||||||
<t t-set="bu" t-value="child"/>
|
|
||||||
<t t-set="klass" t-value="'btn-group-ssm'"/>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</t>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
<table class="table table-condensed">
|
<table class="table table-condensed">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="runbot.build_error">
|
<template id="runbot.build_error">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class='col-md-12'>
|
<div class='col-md-12'>
|
||||||
@ -96,7 +96,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="runbot.team">
|
<template id="runbot.team">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<div class="container-fluid bg-light">
|
<div class="container-fluid bg-light">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div t-if="team" class='col-md-12'>
|
<div t-if="team" class='col-md-12'>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.build_stats">
|
<template id="runbot.build_stats">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<t t-set="bundles" t-value="build.slot_ids.mapped('batch_id.bundle_id')"/>
|
<t t-set="bundles" t-value="build.slot_ids.mapped('batch_id.bundle_id')"/>
|
||||||
<div>
|
<div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -63,7 +63,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="runbot.modules_stats">
|
<template id="runbot.modules_stats">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<input type="hidden" id="bundle_id" t-att-value="bundle.id"/>
|
<input type="hidden" id="bundle_id" t-att-value="bundle.id"/>
|
||||||
<input type="hidden" id="trigger_id" t-att-value="trigger.id"/>
|
<input type="hidden" id="trigger_id" t-att-value="trigger.id"/>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.bundle">
|
<template id="runbot.bundle">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class='col-md-12'>
|
<div class='col-md-12'>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="runbot.commit">
|
<template id="runbot.commit">
|
||||||
<t t-call='website.layout'>
|
<t t-call='runbot.layout'>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Commit base informations -->
|
<!-- Commit base informations -->
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.glances">
|
<template id="runbot.glances">
|
||||||
<t t-call='portal.frontend_layout'>
|
<t t-call="runbot.layout">
|
||||||
<t t-set="head">
|
<t t-set="head">
|
||||||
<t t-if="refresh">
|
<t t-if="refresh">
|
||||||
<meta http-equiv="refresh" t-att-content="refresh"/>
|
<meta http-equiv="refresh" t-att-content="refresh"/>
|
||||||
@ -37,7 +37,7 @@
|
|||||||
</t>
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="frontend_no_nav" inherit_id="portal.frontend_layout" primary="True">
|
<template id="frontend_no_nav" inherit_id="runbot.layout" primary="True">
|
||||||
<xpath expr="//header" position="replace">
|
<xpath expr="//header" position="replace">
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<template id="runbot.bundles">
|
<template id="runbot.bundles">
|
||||||
<t t-call='web.frontend_layout'>
|
<t t-call='runbot.layout'>
|
||||||
<t t-set="nav_form">
|
<t t-set="nav_form">
|
||||||
<form class="form-inline my-2 my-lg-0" role="search" t-att-action="qu(search='')" method="get">
|
<form class="form-inline my-2 my-lg-0" role="search" t-att-action="qu(search='')" method="get">
|
||||||
<div class="input-group md-form form-sm form-2 pl-0">
|
<div class="input-group md-form form-sm form-2 pl-0">
|
||||||
<input class="form-control my-0 py-1 red-border" type="text" placeholder="Search" aria-label="Search" name="search" t-att-value="search"/>
|
<input class="form-control my-0 py-1" type="text" placeholder="Search" aria-label="Search" name="search" t-att-value="search"/>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type='submit' class="input-group-text red lighten-3" id="basic-text1">
|
<button type='submit' class="input-group-text red lighten-3" id="basic-text1">
|
||||||
<i class="fa fa-search text-grey"/>
|
<i class="fa fa-search text-grey"/>
|
||||||
@ -79,15 +79,17 @@
|
|||||||
<t t-if="batch.state=='done' and all(slot.build_id.global_result == 'ok' for slot in batch.slot_ids if slot.build_id)" t-set="klass">success</t>
|
<t t-if="batch.state=='done' and all(slot.build_id.global_result == 'ok' for slot in batch.slot_ids if slot.build_id)" t-set="klass">success</t>
|
||||||
<t t-if="batch.state=='done' and any(slot.build_id.global_result in ('ko', 'warn') for slot in batch.slot_ids)" t-set="klass">danger</t>
|
<t t-if="batch.state=='done' and any(slot.build_id.global_result in ('ko', 'warn') for slot in batch.slot_ids)" t-set="klass">danger</t>
|
||||||
|
|
||||||
<div t-attf-class="batch_tile {{'more' if more else 'nomore'}}">
|
<div t-attf-class="batch_tile if more">
|
||||||
<div t-attf-class="card bg-{{klass}}-light">
|
<div t-attf-class="card bg-{{klass}}-light">
|
||||||
<div class="batch_header">
|
<a t-attf-href="/runbot/batch/#{batch.id}" title="View Batch">
|
||||||
<a t-attf-href="/runbot/batch/#{batch.id}" t-attf-class="badge badge-{{'warning' if batch.has_warning else 'light'}}" title="View Batch">
|
<div class="batch_header">
|
||||||
<t t-esc="batch.get_formated_age()"/>
|
<span t-attf-class="badge badge-{{'warning' if batch.has_warning else 'light'}}">
|
||||||
<i class="fa fa-exclamation-triangle" t-if="batch.has_warning"/>
|
<t t-esc="batch.get_formated_age()"/>
|
||||||
<i class="arrow fa fa-window-maximize"/>
|
<i class="fa fa-exclamation-triangle" t-if="batch.has_warning"/>
|
||||||
</a>
|
</span>
|
||||||
</div>
|
<span class="float-right header_hover">View batch...</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
<t t-if="batch.state=='preparing'">
|
<t t-if="batch.state=='preparing'">
|
||||||
<span><i class="fa fa-cog fa-spin fa-fw"/> preparing</span>
|
<span><i class="fa fa-cog fa-spin fa-fw"/> preparing</span>
|
||||||
</t>
|
</t>
|
||||||
@ -100,7 +102,7 @@
|
|||||||
</t>
|
</t>
|
||||||
<div class="slot_filler" t-foreach="range(10)" t-as="x"/>
|
<div class="slot_filler" t-foreach="range(10)" t-as="x"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="batch_commits">
|
<div t-if='more' class="batch_commits">
|
||||||
<div t-foreach="batch.commit_link_ids.sorted(lambda cl: (cl.commit_id.repo_id.sequence, cl.commit_id.repo_id.id))" t-as="commit_link" class="one_line">
|
<div t-foreach="batch.commit_link_ids.sorted(lambda cl: (cl.commit_id.repo_id.sequence, cl.commit_id.repo_id.id))" t-as="commit_link" class="one_line">
|
||||||
|
|
||||||
<a t-attf-href="/runbot/commit/#{commit_link.commit_id.id}" t-attf-class="badge badge-light batch_commit match_type_{{commit_link.match_type}}">
|
<a t-attf-href="/runbot/commit/#{commit_link.commit_id.id}" t-attf-class="badge badge-light batch_commit match_type_{{commit_link.match_type}}">
|
||||||
|
@ -2,136 +2,153 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<!-- base layout -->
|
<!-- base layout -->
|
||||||
<template id="runbot.layout" inherit_id="website.layout" name="Custom website layout">
|
<template id="runbot.base_page">
|
||||||
<xpath expr="//head/meta[last()]" position="after">
|
<html>
|
||||||
<t t-if="refresh">
|
<head>
|
||||||
<meta http-equiv="refresh" t-att-content="refresh"/>
|
<title t-esc="title or 'Runbot'"/>
|
||||||
</t>
|
<link rel="stylesheet" type="text/css" href="/web/static/lib/bootstrap/css/bootstrap.css"/>
|
||||||
</xpath>
|
<link rel="stylesheet" type="text/css" href="/web/static/lib/fontawesome/css/font-awesome.css"/>
|
||||||
<xpath expr="//footer" position="replace">
|
<link rel="stylesheet" type="text/css" href="/runbot/static/src/css/runbot.css"/>
|
||||||
</xpath>
|
|
||||||
<xpath expr="//nav[hasclass('navbar')]" position="replace">
|
|
||||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
|
||||||
<a t-if="project" t-att-href="qu(search=search)">
|
|
||||||
<b style="color:#777;">
|
|
||||||
<t t-esc="project.name"/>
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#top_menu_collapse">
|
|
||||||
<span class="navbar-toggler-icon"/>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="top_menu_collapse">
|
|
||||||
<ul class="nav navbar-nav ml-auto text-right" id="top_menu">
|
|
||||||
<t t-if="projects">
|
|
||||||
<t t-foreach="projects" t-as="l_project">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" t-att-href="qu('/runbot/%s' % slug(l_project), search=search)">
|
|
||||||
<t t-esc="l_project.name"/>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</t>
|
|
||||||
</t>
|
|
||||||
<li class="nav-item divider"/>
|
|
||||||
<li class="nav-item dropdown">
|
|
||||||
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
|
||||||
<i class="fa fa-gear"/>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu" role="menu">
|
|
||||||
<form class="px-4 py-3" method="post" action="/runbot/submit">
|
|
||||||
<input type="hidden" name="save" value="1"/>
|
|
||||||
<input type="hidden" name="redirect" t-att-value="current_path"/>
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<input type="checkbox" name="more" id="more" t-att-checked="more"/>
|
|
||||||
<label for="more">More info</label>
|
|
||||||
</div>
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<input type="checkbox" name="keep_search" id="keep_search" t-att-checked="keep_search"/>
|
|
||||||
<label for="keep_search">Persistent search</label>
|
|
||||||
</div>
|
|
||||||
<hr class="separator"/>
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<label for="filter_mode">Filter</label>
|
|
||||||
<select class="form-control" name="filter_mode" id="filter_mode">
|
|
||||||
<option value="all" t-att-selected="filter_mode=='all'">All</option>
|
|
||||||
<option value="sticky" t-att-selected="filter_mode=='sticky'">Sticky only</option>
|
|
||||||
<option value="nosticky" t-att-selected="filter_mode=='nosticky'">Dev only</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div t-if="categories" class="text-nowrap">
|
|
||||||
<label for="category">Category</label>
|
|
||||||
<select class="form-control" name="category" id="category">
|
|
||||||
<option t-foreach="categories" t-as="category" t-att-value="category.id" t-esc="category.name" t-att-selected="category.id==active_category_id"/>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<hr class="separator"/>
|
|
||||||
<t t-if="triggers">
|
|
||||||
<input type="hidden" name="update_triggers" t-att-value="project.id"/>
|
|
||||||
<t t-foreach="triggers" t-as="trigger">
|
|
||||||
<div class="text-nowrap">
|
|
||||||
<input type="checkbox" t-attf-name="trigger_{{trigger.id}}" t-attf-id="trigger_{{trigger.id}}" t-att-checked="trigger_display is None or trigger.id in trigger_display"/>
|
|
||||||
<label t-attf-for="trigger_{{trigger.id}}" t-esc="trigger.name"/>
|
|
||||||
</div>
|
|
||||||
</t>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Save</button>
|
<script src="/web/static/lib/jquery/jquery.js" type="text/javascript"/>
|
||||||
</form>
|
<script type="text/javascript" src="/web/static/lib/popper/popper.js"/>
|
||||||
</div>
|
<script type="text/javascript" src="/web/static/lib/bootstrap/js/util.js"/>
|
||||||
</li>
|
<script type="text/javascript" src="/web/static/lib/bootstrap/js/dropdown.js"/>
|
||||||
<li class="nav-item divider" t-ignore="true"/>
|
<script type="text/javascript" src="/web/static/lib/bootstrap/js/collapse.js"/>
|
||||||
<t t-if="not user_id._is_public()">
|
<script type="text/javascript" src="/runbot/static/src/js/runbot.js"/>
|
||||||
<t t-if="nb_assigned_errors and nb_assigned_errors > 0">
|
|
||||||
|
<t t-if="refresh">
|
||||||
|
<meta http-equiv="refresh" t-att-content="refresh"/>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<t t-raw="0"/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="runbot.layout" inherit_id="runbot.base_page" primary="True">
|
||||||
|
<xpath expr="//body" position="replace">
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||||
|
<a t-if="project" t-att-href="qu(search=search)">
|
||||||
|
<b style="color:#777;">
|
||||||
|
<t t-esc="project.name"/>
|
||||||
|
</b>
|
||||||
|
</a>
|
||||||
|
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#top_menu_collapse">
|
||||||
|
<span class="navbar-toggler-icon"/>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="top_menu_collapse">
|
||||||
|
<ul class="nav navbar-nav ml-auto text-right" id="top_menu">
|
||||||
|
<t t-if="projects">
|
||||||
|
<t t-foreach="projects" t-as="l_project">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" t-att-href="qu('/runbot/%s' % slug(l_project), search=search)">
|
||||||
|
<t t-esc="l_project.name"/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
<li class="nav-item divider"/>
|
<li class="nav-item divider"/>
|
||||||
<li class="nav-item">
|
<li class="nav-item dropdown">
|
||||||
<a href="/runbot/errors" class="nav-link text-danger" t-attf-title="You have {{nb_assigned_errors}} random bug assigned"><i class="fa fa-bug"/><t t-esc="nb_assigned_errors"/></a>
|
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
||||||
</li>
|
<i class="fa fa-gear"/>
|
||||||
</t>
|
|
||||||
<t t-elif="nb_build_errors and nb_build_errors > 0">
|
|
||||||
<li class="nav-item divider"/>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="/runbot/errors" class="nav-link" title="Random Bugs"><i class="fa fa-bug"/></a>
|
|
||||||
</li>
|
|
||||||
</t>
|
|
||||||
<li class="nav-item dropdown" t-ignore="true">
|
|
||||||
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
|
||||||
<b>
|
|
||||||
<span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/>
|
|
||||||
</b>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu js_usermenu" role="menu">
|
|
||||||
<a class="dropdown-item" id="o_logout" role="menuitem" t-attf-href="/web/session/logout?redirect=/">Logout</a>
|
|
||||||
<a class="dropdown-item" role="menuitem" t-attf-href="/web">Web</a>
|
|
||||||
<div t-if="user_id.runbot_team_ids" class="dropdown-divider"/>
|
|
||||||
<div t-if="user_id.runbot_team_ids" class="dropdown-header">Teams</div>
|
|
||||||
<a t-foreach="user_id.runbot_team_ids" t-as="team" class="dropdown-item" role="menuitem" t-attf-href="/runbot/teams/{{team.id}}">
|
|
||||||
<t t-esc="team.name.capitalize()"/>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<div class="dropdown-menu" role="menu">
|
||||||
</li>
|
<form class="px-4 py-3" method="post" action="/runbot/submit">
|
||||||
</t>
|
<input type="hidden" name="save" value="1"/>
|
||||||
<t t-else="">
|
<input type="hidden" name="redirect" t-att-value="current_path"/>
|
||||||
<li class="nav-item dropdown" t-ignore="true">
|
<div class="text-nowrap">
|
||||||
<b>
|
<input type="checkbox" name="more" id="more" t-att-checked="more"/>
|
||||||
<a class="nav-link" t-attf-href="/web/login?redirect=/">Login</a>
|
<label for="more">More info</label>
|
||||||
</b>
|
</div>
|
||||||
</li>
|
<div class="text-nowrap">
|
||||||
</t>
|
<input type="checkbox" name="keep_search" id="keep_search" t-att-checked="keep_search"/>
|
||||||
</ul>
|
<label for="keep_search">Persistent search</label>
|
||||||
<t t-raw="nav_form or ''">
|
</div>
|
||||||
</t>
|
<hr class="separator"/>
|
||||||
</div>
|
<div class="text-nowrap">
|
||||||
</nav>
|
<label for="filter_mode">Filter</label>
|
||||||
|
<select class="form-control" name="filter_mode" id="filter_mode">
|
||||||
|
<option value="all" t-att-selected="filter_mode=='all'">All</option>
|
||||||
|
<option value="sticky" t-att-selected="filter_mode=='sticky'">Sticky only</option>
|
||||||
|
<option value="nosticky" t-att-selected="filter_mode=='nosticky'">Dev only</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div t-if="categories" class="text-nowrap">
|
||||||
|
<label for="category">Category</label>
|
||||||
|
<select class="form-control" name="category" id="category">
|
||||||
|
<option t-foreach="categories" t-as="category" t-att-value="category.id" t-esc="category.name" t-att-selected="category.id==active_category_id"/>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<hr class="separator"/>
|
||||||
|
<t t-if="triggers">
|
||||||
|
<input type="hidden" name="update_triggers" t-att-value="project.id"/>
|
||||||
|
<t t-foreach="triggers" t-as="trigger">
|
||||||
|
<div class="text-nowrap">
|
||||||
|
<input type="checkbox" t-attf-name="trigger_{{trigger.id}}" t-attf-id="trigger_{{trigger.id}}" t-att-checked="trigger_display is None or trigger.id in trigger_display"/>
|
||||||
|
<label t-attf-for="trigger_{{trigger.id}}" t-esc="trigger.name"/>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
<button type="submit" class="btn btn-primary">Save</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item divider" t-ignore="true"/>
|
||||||
|
<t t-if="not user_id._is_public()">
|
||||||
|
<t t-call="runbot.build_errors_link"/>
|
||||||
|
<li class="nav-item dropdown" t-ignore="true">
|
||||||
|
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<b>
|
||||||
|
<span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/>
|
||||||
|
</b>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu js_usermenu" role="menu">
|
||||||
|
<a class="dropdown-item" id="o_logout" role="menuitem" t-attf-href="/web/session/logout?redirect=/">Logout</a>
|
||||||
|
<a class="dropdown-item" role="menuitem" t-attf-href="/web">Web</a>
|
||||||
|
<div t-if="user_id.runbot_team_ids" class="dropdown-divider"/>
|
||||||
|
<div t-if="user_id.runbot_team_ids" class="dropdown-header">Teams</div>
|
||||||
|
<a t-foreach="user_id.runbot_team_ids" t-as="team" class="dropdown-item" role="menuitem" t-attf-href="/runbot/teams/{{team.id}}">
|
||||||
|
<t t-esc="team.name.capitalize()"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<li class="nav-item dropdown" t-ignore="true">
|
||||||
|
<b>
|
||||||
|
<a class="nav-link" t-attf-href="/web/login?redirect=/">Login</a>
|
||||||
|
</b>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
|
</ul>
|
||||||
|
<t t-raw="nav_form or ''">
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<t t-raw="0"/>
|
||||||
|
</body>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- remove black bar with app switcher -->
|
<template id="runbot.build_errors_link">
|
||||||
<template id="inherits_no_black_bar" inherit_id="website.user_navbar" name="Inherits No black user_navbar">
|
<t t-if="nb_assigned_errors and nb_assigned_errors > 0">
|
||||||
<xpath expr="//nav[@id='oe_main_menu_navbar']" position="attributes">
|
<li class="nav-item divider"/>
|
||||||
<attribute name="groups">base.group_website_publisher</attribute>
|
<li class="nav-item">
|
||||||
</xpath>
|
<a href="/runbot/errors" class="nav-link text-danger" t-attf-title="You have {{nb_assigned_errors}} random bug assigned"><i class="fa fa-bug"/><t t-esc="nb_assigned_errors"/></a>
|
||||||
<xpath expr="//t[@t-set='body_classname']" position="attributes">
|
</li>
|
||||||
<attribute name="t-value">'o_connected_user' if env['ir.ui.view'].user_has_groups('base.group_website_publisher') else None</attribute>
|
</t>
|
||||||
</xpath>
|
<t t-elif="nb_build_errors and nb_build_errors > 0">
|
||||||
|
<li class="nav-item divider"/>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="/runbot/errors" class="nav-link" title="Random Bugs"><i class="fa fa-bug"/></a>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="runbot.slots_infos" name="Hosts slot nb pending/testing/slots">
|
<template id="runbot.slots_infos" name="Hosts slot nb pending/testing/slots">
|
||||||
@ -163,7 +180,7 @@
|
|||||||
<span t-attf-class="btn btn-{{color}} disabled" t-att-title="slot.link_type">
|
<span t-attf-class="btn btn-{{color}} disabled" t-att-title="slot.link_type">
|
||||||
<i t-attf-class="fa fa-{{slot.fa_link_type()}}"/>
|
<i t-attf-class="fa fa-{{slot.fa_link_type()}}"/>
|
||||||
</span>
|
</span>
|
||||||
<a t-if="bu" t-attf-href="/runbot/build/#{bu.id}" t-attf-class="btn btn-default slot_name">
|
<a t-if="bu" t-attf-href="/runbot/batch/{{slot.batch_id.id}}/build/#{bu.id}" t-attf-class="btn btn-default slot_name">
|
||||||
<span t-esc="slot.trigger_id.name"/>
|
<span t-esc="slot.trigger_id.name"/>
|
||||||
</a>
|
</a>
|
||||||
<span t-else="" t-attf-class="btn btn-default disabled slot_name">
|
<span t-else="" t-attf-class="btn btn-default disabled slot_name">
|
||||||
@ -181,10 +198,10 @@
|
|||||||
<template id="runbot.build_button">
|
<template id="runbot.build_button">
|
||||||
<div t-attf-class="pull-right">
|
<div t-attf-class="pull-right">
|
||||||
<div t-attf-class="btn-group {{klass}}">
|
<div t-attf-class="btn-group {{klass}}">
|
||||||
<a t-if="bu.local_state == 'running' and bu.database_ids" t-attf-href="http://{{sorted(bu.mapped('database_ids.name'))[0]}}.{{bu.host}}" class="btn btn-primary" title="Sign in on this build" aria-label="Sign in on this build">
|
<a t-if="bu.local_state == 'running' and bu.database_ids" t-attf-href="http://{{sorted(bu.mapped('database_ids.name'))[0]}}.{{bu.host}}" class="btn btn-info" title="Sign in on this build" aria-label="Sign in on this build">
|
||||||
<i class="fa fa-sign-in"/>
|
<i class="fa fa-sign-in"/>
|
||||||
</a>
|
</a>
|
||||||
<a t-if="bu.static_run" t-att-href="bu.static_run" class="btn btn-primary" title="View result" aria-label="View result">
|
<a t-if="bu.static_run" t-att-href="bu.static_run" class="btn btn-info" title="View result" aria-label="View result">
|
||||||
<i class="fa fa-sign-in"/>
|
<i class="fa fa-sign-in"/>
|
||||||
</a>
|
</a>
|
||||||
<a t-if="bu.local_state=='done' and bu.requested_action != 'wake_up' and bu.database_ids" href="#" data-runbot="wakeup" t-att-data-runbot-build="bu.id" class="btn btn-default" title="Wake up this build" aria-label="Wake up this build">
|
<a t-if="bu.local_state=='done' and bu.requested_action != 'wake_up' and bu.database_ids" href="#" data-runbot="wakeup" t-att-data-runbot-build="bu.id" class="btn btn-default" title="Wake up this build" aria-label="Wake up this build">
|
||||||
@ -255,7 +272,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<a groups="base.group_user" data-runbot="kill" class="dropdown-item disabled">
|
<a groups="base.group_user" class="dropdown-item disabled">
|
||||||
<i class="fa fa-spinner fa-spin"/>
|
<i class="fa fa-spinner fa-spin"/>
|
||||||
Killing
|
Killing
|
||||||
<i class="fa fa-crosshairs"/>
|
<i class="fa fa-crosshairs"/>
|
||||||
@ -270,7 +287,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<a groups="base.group_user" class="dropdown-item disabled" data-runbot="wakeup">
|
<a groups="base.group_user" class="dropdown-item disabled">
|
||||||
<i class="fa fa-spinner fa-spin"/>
|
<i class="fa fa-spinner fa-spin"/>
|
||||||
Waking up
|
Waking up
|
||||||
<i class="fa fa-crosshairs"/>
|
<i class="fa fa-crosshairs"/>
|
||||||
|
@ -108,7 +108,6 @@
|
|||||||
</record>
|
</record>
|
||||||
<record id="bundle_runbot_13_dev_tri" model="runbot.bundle">
|
<record id="bundle_runbot_13_dev_tri" model="runbot.bundle">
|
||||||
<field name="name">13.0-dev-tri</field>
|
<field name="name">13.0-dev-tri</field>
|
||||||
<field name="is_base">True</field>
|
|
||||||
<field name="project_id" ref="project_runbot"/>
|
<field name="project_id" ref="project_runbot"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class Runbot(models.AbstractModel):
|
|||||||
|
|
||||||
assert bundles|self.env.ref('runbot.bundle_dummy') == bundles.search([])
|
assert bundles|self.env.ref('runbot.bundle_dummy') == bundles.search([])
|
||||||
|
|
||||||
if False and bundles.branch_ids:
|
if bundles.branch_ids:
|
||||||
# only populate data if no branch are found
|
# only populate data if no branch are found
|
||||||
return
|
return
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user