This commit is contained in:
Christophe Monniez 2022-09-20 07:42:50 +02:00
parent 0ea9c4aefe
commit 147fc73078
6 changed files with 185 additions and 67 deletions

View File

@ -25,14 +25,12 @@ def route(routes, **kw):
@functools.wraps(f) @functools.wraps(f)
def response_wrap(*args, **kwargs): def response_wrap(*args, **kwargs):
projects = request.env['runbot.project'].search([]) projects = request.env['runbot.project'].search([])
more = request.httprequest.cookies.get('more', False) == '1'
filter_mode = request.httprequest.cookies.get('filter_mode', 'all') filter_mode = request.httprequest.cookies.get('filter_mode', 'all')
keep_search = request.httprequest.cookies.get('keep_search', False) == '1' keep_search = request.httprequest.cookies.get('keep_search', False) == '1'
cookie_search = request.httprequest.cookies.get('search', '') cookie_search = request.httprequest.cookies.get('search', '')
refresh = kwargs.get('refresh', False) refresh = kwargs.get('refresh', False)
nb_build_errors = request.env['runbot.build.error'].search_count([('random', '=', True), ('parent_id', '=', False)]) nb_build_errors = request.env['runbot.build.error'].search_count([('random', '=', True), ('parent_id', '=', False)])
nb_assigned_errors = request.env['runbot.build.error'].search_count([('responsible', '=', request.env.user.id)]) nb_assigned_errors = request.env['runbot.build.error'].search_count([('responsible', '=', request.env.user.id)])
kwargs['more'] = more
kwargs['projects'] = projects kwargs['projects'] = projects
response = f(*args, **kwargs) response = f(*args, **kwargs)
@ -47,7 +45,6 @@ def route(routes, **kw):
project = response.qcontext.get('project') or projects[0] project = response.qcontext.get('project') or projects[0]
response.qcontext['projects'] = projects response.qcontext['projects'] = projects
response.qcontext['more'] = more
response.qcontext['keep_search'] = keep_search response.qcontext['keep_search'] = keep_search
response.qcontext['search'] = search response.qcontext['search'] = search
response.qcontext['current_path'] = request.httprequest.full_path response.qcontext['current_path'] = request.httprequest.full_path
@ -78,9 +75,8 @@ class Runbot(Controller):
@o_route([ @o_route([
'/runbot/submit' '/runbot/submit'
], type='http', auth="public", methods=['GET', 'POST'], csrf=False) ], type='http', auth="public", methods=['GET', 'POST'], csrf=False)
def submit(self, more=False, redirect='/', keep_search=False, category=False, filter_mode=False, update_triggers=False, **kwargs): def submit(self, redirect='/', keep_search=False, category=False, filter_mode=False, update_triggers=False, **kwargs):
response = werkzeug.utils.redirect(redirect) response = werkzeug.utils.redirect(redirect)
response.set_cookie('more', '1' if more else '0')
response.set_cookie('keep_search', '1' if keep_search else '0') response.set_cookie('keep_search', '1' if keep_search else '0')
response.set_cookie('filter_mode', filter_mode or 'all') response.set_cookie('filter_mode', filter_mode or 'all')
response.set_cookie('category', category or '0') response.set_cookie('category', category or '0')
@ -101,8 +97,9 @@ class Runbot(Controller):
@route(['/', @route(['/',
'/runbot', '/runbot',
'/runbot/<model("runbot.project"):project>', '/runbot/<model("runbot.project"):project>',
'/runbot/<model("runbot.project"):project>/search/<search>'], website=True, auth='public', type='http') '/runbot/<model("runbot.project"):project>/search/<search>',
def bundles(self, project=None, search='', projects=False, refresh=False, **kwargs): '/runbot/page/<int:page>'], website=True, auth='public', type='http')
def bundles(self, limit=40, page=1, project=None, search='', projects=False, refresh=False, **kwargs):
search = search if len(search) < 60 else search[:60] search = search if len(search) < 60 else search[:60]
env = request.env env = request.env
categories = env['runbot.category'].search([]) categories = env['runbot.category'].search([])
@ -149,8 +146,21 @@ class Runbot(Controller):
case when "runbot_bundle".sticky then "runbot_bundle".version_number end collate "C" desc, case when "runbot_bundle".sticky then "runbot_bundle".version_number end collate "C" desc,
"runbot_bundle".last_batch desc "runbot_bundle".last_batch desc
""" """
query.limit=40
bundles = env['runbot.bundle'].browse(query) bundle_count = request.env['runbot.bundle.pr'].search_count(domain)
limit = min(float(limit), 200)
pager = request.website.pager(
url='/runbot/',
url_args={'search': search},
total=bundle_count,
scope=3,
page=page,
step=limit,
)
query.limit = limit
query.offset = pager.get('offset', 0)
bundles_pr = env['runbot.bundle.pr'].browse(query)
bundles = env['runbot.bundle'].browse(bundles_pr.ids)
category_id = int(request.httprequest.cookies.get('category') or 0) or request.env['ir.model.data']._xmlid_to_res_id('runbot.default_category') category_id = int(request.httprequest.cookies.get('category') or 0) or request.env['ir.model.data']._xmlid_to_res_id('runbot.default_category')
@ -161,6 +171,7 @@ class Runbot(Controller):
triggers = env['runbot.trigger'].search([('project_id', '=', project.id)]) triggers = env['runbot.trigger'].search([('project_id', '=', project.id)])
context.update({ context.update({
'pager': pager,
'active_category_id': category_id, 'active_category_id': category_id,
'bundles': bundles, 'bundles': bundles,
'project': project, 'project': project,
@ -168,6 +179,14 @@ class Runbot(Controller):
'trigger_display': trigger_display, 'trigger_display': trigger_display,
}) })
pr_filters = {
'all': { 'text': 'All', 'domain': False},
'has_pr': { 'text': 'With Pull Request(s)', 'domain': ('pr_count', '>', 0)},
'has_no_pr': { 'text': 'Without Pull Request(s)', 'domain': ('pr_count', '=', 0)},
'has_open_pr': { 'text': 'With Open Pull Request(s)', 'domain': ('pr_open_count', '>', 0)},
'has_no_open_pr': { 'text': 'Without Open Pull Request(s)', 'domain': ('pr_open_count', '=', 0)},
}
context.update({'message': request.env['ir.config_parameter'].sudo().get_param('runbot.runbot_message')}) context.update({'message': request.env['ir.config_parameter'].sudo().get_param('runbot.runbot_message')})
res = request.render('runbot.bundles', context) res = request.render('runbot.bundles', context)
return res return res

View File

@ -270,7 +270,10 @@ class BundlePr(models.Model):
id = fields.Many2one('runbot.bundle', string='Bundle', readonly=True) id = fields.Many2one('runbot.bundle', string='Bundle', readonly=True)
name = fields.Char(string='Bundle Name', readonly=True) name = fields.Char(string='Bundle Name', readonly=True)
project_id = fields.Many2one('runbot.project', readonly=True) project_id = fields.Many2one('runbot.project', readonly=True)
no_build = fields.Boolean('No build', readonly=True)
last_batch = fields.Many2one('runbot.batch', readonly=True)
is_base = fields.Boolean('Is base', readonly=True) is_base = fields.Boolean('Is base', readonly=True)
sticky = fields.Boolean('Sticky', readonly=True)
owner_id = fields.Many2one('res.users', string='Bundle Owner', readonly=True) owner_id = fields.Many2one('res.users', string='Bundle Owner', readonly=True)
tags = fields.Char('Comma Separated Tags', readonly=True) tags = fields.Char('Comma Separated Tags', readonly=True)
branch_count = fields.Integer('Branch count', readonly=True) branch_count = fields.Integer('Branch count', readonly=True)
@ -278,6 +281,7 @@ class BundlePr(models.Model):
pr_open_count = fields.Integer('Open PR count', readonly=True) pr_open_count = fields.Integer('Open PR count', readonly=True)
pr_closed_count = fields.Integer('Closed PR count', readonly=True) pr_closed_count = fields.Integer('Closed PR count', readonly=True)
def init(self): def init(self):
""" Create an SQL view for bundle """ """ Create an SQL view for bundle """
tools.drop_view_if_exists(self._cr, 'runbot_bundle_pr') tools.drop_view_if_exists(self._cr, 'runbot_bundle_pr')
@ -287,7 +291,10 @@ class BundlePr(models.Model):
runbot_bundle.id AS id, runbot_bundle.id AS id,
runbot_bundle.name AS name, runbot_bundle.name AS name,
runbot_bundle.project_id AS project_id, runbot_bundle.project_id AS project_id,
runbot_bundle.no_build AS no_build,
runbot_bundle.last_batch AS last_batch,
runbot_bundle.is_base AS is_base, runbot_bundle.is_base AS is_base,
runbot_bundle.sticky AS sticky,
runbot_bundle.owner_id AS owner_id, runbot_bundle.owner_id AS owner_id,
STRING_AGG(runbot_bundle_tag.name,',') AS tags, STRING_AGG(runbot_bundle_tag.name,',') AS tags,
count(runbot_branch.id) AS branch_count, count(runbot_branch.id) AS branch_count,

View File

@ -30,3 +30,17 @@ function copyToClipboard(text) {
} }
navigator.clipboard.writeText(text); navigator.clipboard.writeText(text);
} }
function toggleMoreInfo() {
let batches_commits_infos = document.getElementsByClassName("batch_commits");
for (let i = 0; i < batches_commits_infos.length; i++) {
info_block = batches_commits_infos[i];
console.log(info_block.style.display);
if (info_block.style.display === "none") {
info_block.style.display = "block";
}
else {
info_block.style.display = "none";
}
}
}

View File

@ -3,6 +3,66 @@
<data> <data>
<template id="runbot.bundle_list"> <template id="runbot.bundle_list">
<t t-call="runbot.layout"> <t t-call="runbot.layout">
<t t-set="nav_form">
<t t-call="website.website_search_box_input">
<t t-set="_form_classes" t-valuef="mt8 float-right"/>
<t t-set="action" t-valuef="/runbot/bundle"/>
<t t-set="placeholder">Search Bundle Names</t>
<t t-set="search" t-value="search"/>
<div class="d-flex">
<span class="navbar-brand h4 my-0 mr-auto">Filters</span>
<ul class="nav">
<li class="nav-item dropdown mr-2 my-1">
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-filter"/>PR
</a>
<div class="dropdown-menu">
<t t-foreach="pr_filters" t-as="pr_filter">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', pr_filter=pr_filter if pr_filter != 'all' else None) }}">
<span t-esc="pr_filters[pr_filter].get('text')"/>
</a>
</t>
</div>
</li>
<li class="nav-item dropdown mr-2 my-1">
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-users"/>Team
</a>
<div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=None) }}">
<span>Any</span>
</a>
<t t-foreach="teams" t-as="team">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=team.id) }}">
<span t-esc="team.name"/>
</a>
</t>
</div>
</li>
<li class="nav-item dropdown mr-2 my-1">
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-tags"/>Tags
</a>
<div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=None) }}">
<span>Any</span>
</a>
<t t-foreach="tags" t-as="tag">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=tag.id) }}">
<span t-esc="tag.name"/>
</a>
</t>
</div>
</li>
</ul>
</div>
</t>
</t>
<t t-call="runbot.bundle_list_top_bar" /> <t t-call="runbot.bundle_list_top_bar" />
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
@ -57,63 +117,57 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="d-flex flex-column flex-sm-row justify-content-between w-100"> <div class="d-flex flex-column flex-sm-row justify-content-between w-100">
<t t-call="website.pager" /> <t t-call="website.pager" />
<span class="navbar-brand h4 my-0 mr-auto">Filters</span> <div class="d-flex">
<ul class="nav"> <span class="navbar-brand h4 my-0 mr-auto">Filters</span>
<li class="nav-item dropdown mr-2 my-1"> <ul class="nav">
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> <li class="nav-item dropdown mr-2 my-1">
<i class="fa fa-filter"/>PR <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
</a> <i class="fa fa-filter"/>PR
<div class="dropdown-menu">
<t t-foreach="pr_filters" t-as="pr_filter">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', pr_filter=pr_filter if pr_filter != 'all' else None) }}">
<span t-esc="pr_filters[pr_filter].get('text')"/>
</a>
</t>
</div>
</li>
<li class="nav-item dropdown mr-2 my-1">
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-users"/>Team
</a>
<div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=None) }}">
<span>Any</span>
</a> </a>
<t t-foreach="teams" t-as="team"> <div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between" <t t-foreach="pr_filters" t-as="pr_filter">
t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=team.id) }}"> <a class="dropdown-item d-flex align-items-center justify-content-between"
<span t-esc="team.name"/> t-attf-href="/runbot/bundle?{{ keep_query('*', pr_filter=pr_filter if pr_filter != 'all' else None) }}">
</a> <span t-esc="pr_filters[pr_filter].get('text')"/>
</t> </a>
</div> </t>
</li> </div>
<li class="nav-item dropdown mr-2 my-1"> </li>
<a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown"> <li class="nav-item dropdown mr-2 my-1">
<i class="fa fa-tags"/>Tags <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
</a> <i class="fa fa-users"/>Team
<div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=None) }}">
<span>Any</span>
</a> </a>
<t t-foreach="tags" t-as="tag"> <div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between" <a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=tag.id) }}"> t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=None) }}">
<span t-esc="tag.name"/> <span>Any</span>
</a> </a>
</t> <t t-foreach="teams" t-as="team">
</div> <a class="dropdown-item d-flex align-items-center justify-content-between"
</li> t-attf-href="/runbot/bundle?{{ keep_query('*', team_id=team.id) }}">
</ul> <span t-esc="team.name"/>
<div class="col-md-4 d-none d-md-flex flex-row align-items-center justify-content-end"> </a>
<t t-call="website.website_search_box_input"> </t>
<t t-set="_form_classes" t-valuef="mt8 float-right"/> </div>
<t t-set="action" t-valuef="/runbot/bundle"/> </li>
<t t-set="placeholder">Search Bundle Names</t> <li class="nav-item dropdown mr-2 my-1">
<t t-set="search" t-value="search"/> <a href="#" role="button" class="btn dropdown-toggle" data-toggle="dropdown">
</t> <i class="fa fa-tags"/>Tags
</a>
<div class="dropdown-menu">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=None) }}">
<span>Any</span>
</a>
<t t-foreach="tags" t-as="tag">
<a class="dropdown-item d-flex align-items-center justify-content-between"
t-attf-href="/runbot/bundle?{{ keep_query('*', tag_id=tag.id) }}">
<span t-esc="tag.name"/>
</a>
</t>
</div>
</li>
</ul>
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,6 +4,7 @@
<template id="runbot.bundles"> <template id="runbot.bundles">
<t t-call='runbot.layout'> <t t-call='runbot.layout'>
<t t-set="nav_form"> <t t-set="nav_form">
<t t-call="website.pager" />
<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" 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"/>
@ -73,6 +74,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="pull-right">
<t t-call="website.pager" />
</div>
</t> </t>
</template> </template>
@ -105,7 +109,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 t-if='more' class="batch_commits"> <div class="batch_commits" style="display: none;">
<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}}">

View File

@ -53,6 +53,14 @@
</t> </t>
</t> </t>
<li class="nav-item divider"/> <li class="nav-item divider"/>
<li>
<a href="#" class="nav-link" title="Toggle More Batch Infos" aria-label="Toggle More Batch Infos" onclick="toggleMoreInfo()">
<i t-attf-class="fa fa-info"/>
</a>
</li>
<li class="nav-item divider"/>
<t t-call="runbot.filter_dropdown" />
<li class="nav-item divider"/>
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown"> <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-gear"/> <i class="fa fa-gear"/>
@ -61,10 +69,6 @@
<form class="px-4 py-3" method="post" action="/runbot/submit"> <form class="px-4 py-3" method="post" action="/runbot/submit">
<input type="hidden" name="save" value="1"/> <input type="hidden" name="save" value="1"/>
<input type="hidden" name="redirect" t-att-value="current_path"/> <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"> <div class="text-nowrap">
<input type="checkbox" name="keep_search" id="keep_search" t-att-checked="keep_search"/> <input type="checkbox" name="keep_search" id="keep_search" t-att-checked="keep_search"/>
<label for="keep_search">Persistent search</label> <label for="keep_search">Persistent search</label>
@ -355,5 +359,21 @@
</t> </t>
</div> </div>
</template> </template>
<template id="runbot.filter_dropdown">
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-filter"/>
</a>
<div class="dropdown-menu" role="menu">
<t t-foreach="pr_filters" t-as="pr_filter">
<a class="dropdown-item d-flex align-items-center justify-content-between" t-attf-href="/runbot/bundle?{{ keep_query('*', pr_filter=pr_filter if pr_filter != 'all' else None) }}">
<span t-esc="pr_filters[pr_filter].get('text')"/>
</a>
</t>
<hr class="separator"/>
</div>
</li>
</template>
</data> </data>
</odoo> </odoo>