Added filtration for errors by severity and plugin. Issue #85.

This commit is contained in:
Dmitry Khomutov 2017-10-29 21:26:43 +07:00
parent 6b102f214e
commit 42888630e7
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
8 changed files with 253 additions and 36 deletions

View file

@ -36,12 +36,8 @@ var Build = Class.extend({
$('.errors-table tbody').html(self.buildData.error_html);
$('#paginator').html(self.buildData.paginator);
if (self.buildData.errors == 0) {
$('.errors-label').hide();
} else {
$('.errors-label').text(self.buildData.errors);
$('.errors-label').show();
}
$('.errors-label').text(self.buildData.errors_total);
$('.errors-label').show();
switch (self.buildData.status) {
case 0:
@ -78,7 +74,7 @@ var Build = Class.extend({
var fullUri = window.APP_URL + uri;
if (name == 'build-updated') {
fullUri = window.APP_URL + 'build/ajax-data/' + self.buildId + '?per_page=' + PER_PAGE + '&page=' + PAGE;
fullUri = window.APP_URL + 'build/ajax-data/' + self.buildId + '?per_page=' + PER_PAGE + '&page=' + PAGE + '&plugin=' + BUILD_PLUGIN + '&severity=' + BUI;
}
$.ajax({

View file

@ -50,7 +50,15 @@ class BuildController extends Controller
*/
public function view($buildId)
{
$page = (integer)$this->getParam('page', 1);
$page = (integer)$this->getParam('page', 1);
$plugin = $this->getParam('plugin', '');
$severity = $this->getParam('severity', null);
if (null !== $severity && '' !== $severity) {
$severity = (integer)$severity;
} else {
$severity = null;
}
try {
$build = BuildFactory::getBuildById($buildId);
@ -65,7 +73,7 @@ class BuildController extends Controller
/** @var User $user */
$user = $_SESSION['php-censor-user'];
$perPage = $user->getFinalPerPage();
$data = $this->getBuildData($build, (($page - 1) * $perPage), $perPage);
$data = $this->getBuildData($build, $plugin, $severity, (($page - 1) * $perPage), $perPage);
$pages = ($data['errors'] === 0)
? 1
: (integer)ceil($data['errors'] / $perPage);
@ -74,12 +82,21 @@ class BuildController extends Controller
$page = $pages;
}
$this->view->plugins = $this->getUiPlugins();
/** @var \PHPCensor\Store\BuildErrorStore $errorStore */
$errorStore = b8\Store\Factory::getStore('BuildError');
$this->view->uiPlugins = $this->getUiPlugins();
$this->view->build = $build;
$this->view->data = $data;
$this->view->plugin = urldecode($plugin);
$this->view->plugins = $errorStore->getKnownPlugins($buildId);
$this->view->severity = urldecode(null !== $severity ? $severity : '');
$this->view->severities = $errorStore->getKnownSeverities($buildId, $plugin);
$this->view->page = $page;
$this->view->perPage = $perPage;
$this->view->paginator = $this->getPaginatorHtml($buildId, $data['errors'], $perPage, $page);
$this->view->paginator = $this->getPaginatorHtml($buildId, $plugin, $severity, $data['errors'], $perPage, $page);
$this->layout->title = Lang::get('build_n', $buildId);
$this->layout->subtitle = $build->getProjectTitle();
@ -147,12 +164,14 @@ class BuildController extends Controller
* Get build data from database and json encode it.
*
* @param Build $build
* @param string $plugin
* @param integer $severity
* @param integer $start
* @param integer $perPage
*
* @return array
*/
protected function getBuildData(Build $build, $start = 0, $perPage = 10)
protected function getBuildData(Build $build, $plugin, $severity, $start = 0, $perPage = 10)
{
$data = [];
$data['status'] = (int)$build->getStatus();
@ -164,33 +183,44 @@ class BuildController extends Controller
/** @var \PHPCensor\Store\BuildErrorStore $errorStore */
$errorStore = b8\Store\Factory::getStore('BuildError');
$errors = $errorStore->getByBuildId($build->getId(), $perPage, $start);
$errors = $errorStore->getByBuildId($build->getId(), $perPage, $start, $plugin, $severity);
$errorView = new b8\View('Build/errors');
$errorView->build = $build;
$errorView->errors = $errors['items'];
$data['errors'] = (integer)$errorStore->getErrorTotalForBuild($build->getId());
$data['error_html'] = $errorView->render();
$data['errors'] = (integer)$errorStore->getErrorTotalForBuild($build->getId(), $plugin, $severity);
$data['errors_total'] = (integer)$errorStore->getErrorTotalForBuild($build->getId());
$data['error_html'] = $errorView->render();
return $data;
}
/**
* @param integer $buildId
* @param string $plugin
* @param integer $severity
* @param integer $total
* @param integer $perPage
* @param integer $page
*
* @return string
*/
protected function getPaginatorHtml($buildId, $total, $perPage, $page)
protected function getPaginatorHtml($buildId, $plugin, $severity, $total, $perPage, $page)
{
$view = new b8\View('pagination');
$urlPattern = APP_URL . 'build/view/' . $buildId;
$params = [];
if (!empty($plugin)) {
$params['plugin'] = $plugin;
}
$urlPattern = $urlPattern . '?' . str_replace('%28%3Anum%29', '(:num)', http_build_query(['page' => '(:num)'])) . '#errors';
if (null !== $severity) {
$params['severity'] = $severity;
}
$urlPattern = $urlPattern . '?' . str_replace('%28%3Anum%29', '(:num)', http_build_query(array_merge($params, ['page' => '(:num)']))) . '#errors';
$paginator = new Paginator($total, $perPage, $page, $urlPattern);
$view->paginator = $paginator;
@ -282,6 +312,14 @@ class BuildController extends Controller
{
$page = (integer)$this->getParam('page', 1);
$perPage = (integer)$this->getParam('per_page', 10);
$plugin = $this->getParam('plugin', '');
$severity = $this->getParam('severity', null);
if (null !== $severity && '' !== $severity) {
$severity = (integer)$severity;
} else {
$severity = null;
}
$response = new JsonResponse();
$build = BuildFactory::getBuildById($buildId);
@ -293,8 +331,8 @@ class BuildController extends Controller
return $response;
}
$data = $this->getBuildData($build, (($page - 1) * $perPage), $perPage);
$data['paginator'] = $this->getPaginatorHtml($buildId, $data['errors'], $perPage, $page);
$data = $this->getBuildData($build, $plugin, $severity, (($page - 1) * $perPage), $perPage);
$data['paginator'] = $this->getPaginatorHtml($buildId, $plugin, $severity, $data['errors'], $perPage, $page);
$response->setContent($data);

View file

@ -66,7 +66,7 @@ class ProjectController extends PHPCensor\Controller
$environment = $this->getParam('environment', '');
$page = (integer)$this->getParam('page', 1);
$perPage = (integer)$this->getParam('per_page', 10);
$builds = $this->getLatestBuildsHtml($projectId, $environment, $branch, (($page - 1) * $perPage), $perPage);
$builds = $this->getLatestBuildsHtml($projectId, $branch, $environment, (($page - 1) * $perPage), $perPage);
$this->response->disableLayout();
$this->response->setContent($builds[0]);
@ -97,7 +97,7 @@ class ProjectController extends PHPCensor\Controller
/** @var PHPCensor\Model\User $user */
$user = $_SESSION['php-censor-user'];
$perPage = $user->getFinalPerPage();
$builds = $this->getLatestBuildsHtml($projectId, $environment, $branch, (($page - 1) * $perPage), $perPage);
$builds = $this->getLatestBuildsHtml($projectId, $branch, $environment, (($page - 1) * $perPage), $perPage);
$pages = ($builds[1] === 0)
? 1
: (integer)ceil($builds[1] / $perPage);
@ -252,14 +252,14 @@ class ProjectController extends PHPCensor\Controller
* Render latest builds for project as HTML table.
*
* @param int $projectId
* @param string $environment A urldecoded environment name.
* @param string $branch A urldecoded branch name.
* @param string $branch A urldecoded branch name.
* @param string $environment A urldecoded environment name.
* @param int $start
* @param int $perPage
*
* @return array
*/
protected function getLatestBuildsHtml($projectId, $environment = '', $branch = '', $start = 0, $perPage = 10)
protected function getLatestBuildsHtml($projectId, $branch = '', $environment = '', $start = 0, $perPage = 10)
{
$criteria = ['project_id' => $projectId];

View file

@ -337,6 +337,11 @@ PHP Censor',
'stage_broken' => 'Broken',
'stage_fixed' => 'Fixed',
'severity' => 'Severity',
'all_plugins' => 'All plugins',
'all_severities' => 'All severities',
'filters' => 'Filters',
'errors_selected' => 'Errors selected',
'build_details' => 'Build Details',
'commit_details' => 'Commit Details',

View file

@ -325,7 +325,12 @@ PHP Censor',
'stage_failure' => 'Провал',
'stage_broken' => 'Поломка',
'stage_fixed' => 'Исправление',
'severity' => 'Важность',
'severity' => 'Уровень',
'all_plugins' => 'Все плагины',
'all_severities' => 'Все уровни',
'filters' => 'Фильтры',
'errors_selected' => 'Ошибок выбрано',
'build_details' => 'Информация о сборке',
'commit_details' => 'Информация о коммитe',

View file

@ -401,6 +401,30 @@ class BuildError extends Model
}
}
/**
* Get the language string key for this error's severity level.
*
* @param integer $severity
*
* @return string
*/
public static function getSeverityName($severity)
{
switch ($severity) {
case self::SEVERITY_CRITICAL:
return 'critical';
case self::SEVERITY_HIGH:
return 'high';
case self::SEVERITY_NORMAL:
return 'normal';
case self::SEVERITY_LOW:
return 'low';
}
}
/**
* Get the class to apply to HTML elements representing this error.
*

View file

@ -61,18 +61,27 @@ class BuildErrorStore extends Store
* @param integer $buildId
* @param integer $limit
* @param integer $offset
* @param string $plugin
* @param integer $severity
*
* @return array
*
* @throws HttpException
*/
public function getByBuildId($buildId, $limit = null, $offset = 0)
public function getByBuildId($buildId, $limit = null, $offset = 0, $plugin = null, $severity = null)
{
if (is_null($buildId)) {
throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
}
$query = 'SELECT * FROM {{build_error}} WHERE {{build_id}} = :build_id ORDER BY plugin, severity';
$query = 'SELECT * FROM {{build_error}} WHERE {{build_id}} = :build_id';
if ($plugin) {
$query .= ' AND {{plugin}} = :plugin';
}
if (null !== $severity) {
$query .= ' AND {{severity}} = :severity';
}
$query .= ' ORDER BY plugin, severity';
if (null !== $limit) {
$query .= ' LIMIT :limit';
}
@ -81,6 +90,12 @@ class BuildErrorStore extends Store
}
$stmt = Database::getConnection()->prepareCommon($query);
$stmt->bindValue(':build_id', $buildId);
if ($plugin) {
$stmt->bindValue(':plugin', $plugin, \PDO::PARAM_STR);
}
if (null !== $severity) {
$stmt->bindValue(':severity', (integer)$severity, \PDO::PARAM_INT);
}
if (null !== $limit) {
$stmt->bindValue(':limit', (integer)$limit, \PDO::PARAM_INT);
}
@ -108,17 +123,31 @@ class BuildErrorStore extends Store
* Gets the total number of errors for a given build.
*
* @param integer $buildId
* @param string $plugin
* @param integer $severity
*
* @return array
*/
public function getErrorTotalForBuild($buildId)
public function getErrorTotalForBuild($buildId, $plugin = null, $severity = null)
{
$query = 'SELECT COUNT(*) AS {{total}} FROM {{build_error}}
WHERE {{build_id}} = :build';
if ($plugin) {
$query .= ' AND {{plugin}} = :plugin';
}
if (null !== $severity) {
$query .= ' AND {{severity}} = :severity';
}
$stmt = Database::getConnection('read')->prepareCommon($query);
$stmt->bindValue(':build', $buildId, \PDO::PARAM_INT);
if ($plugin) {
$stmt->bindValue(':plugin', $plugin, \PDO::PARAM_STR);
}
if (null !== $severity) {
$stmt->bindValue(':severity', (integer)$severity, \PDO::PARAM_INT);
}
if ($stmt->execute()) {
$res = $stmt->fetch(\PDO::FETCH_ASSOC);
@ -127,4 +156,62 @@ class BuildErrorStore extends Store
return [];
}
}
/**
* @param integer $buildId
*
* @return array
*/
public function getKnownPlugins($buildId)
{
$query = 'SELECT DISTINCT {{plugin}} from {{build_error}} WHERE {{build_id}} = :build';
$stmt = Database::getConnection('read')->prepareCommon($query);
$stmt->bindValue(':build', $buildId);
if ($stmt->execute()) {
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$map = function ($item) {
return $item['plugin'];
};
$rtn = array_map($map, $res);
return $rtn;
} else {
return [];
}
}
/**
* @param integer $buildId
* @param string $plugin
*
* @return array
*/
public function getKnownSeverities($buildId, $plugin = '')
{
$query = 'SELECT DISTINCT {{severity}} from {{build_error}} WHERE {{build_id}} = :build';
if ($plugin) {
$query .= ' AND {{plugin}} = :plugin';
}
$stmt = Database::getConnection('read')->prepareCommon($query);
$stmt->bindValue(':build', $buildId);
if ($plugin) {
$stmt->bindValue(':plugin', $plugin);
}
if ($stmt->execute()) {
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$map = function ($item) {
return (integer)$item['severity'];
};
$rtn = array_map($map, $res);
return $rtn;
} else {
return [];
}
}
}

View file

@ -2,6 +2,7 @@
use PHPCensor\Helper\Lang;
use PHPCensor\Model\Build;
use PHPCensor\Model\BuildError;
/**
* @var Build $build
@ -172,10 +173,10 @@ use PHPCensor\Model\Build;
<li class="">
<a href="#errors" data-toggle="tab">
<i class="fa fa-exclamation-triangle"></i> <?php print Lang::get('errors'); ?>
<?php if ($data['errors'] == 0): ?>
<?php if ($data['errors_total'] == 0): ?>
<span class="errors-label label label-danger" style="display: none">0</span>
<?php else: ?>
<span class="errors-label label label-danger"><?php print $data['errors']; ?></span>
<span class="errors-label label label-danger"><?php print $data['errors_total']; ?></span>
<?php endif; ?>
</a>
</li>
@ -190,6 +191,65 @@ use PHPCensor\Model\Build;
</div>
<div class="tab-pane" id="errors">
<?php if ($build->getStatus() > Build::STATUS_RUNNING): ?>
<div class="box">
<div class="box-header">
<h3 class="box-title"><?= Lang::get('filters'); ?></h3>
</div>
<div class="box-body">
<?php if ($data['errors'] < $data['errors_total']): ?>
<p><?= Lang::get('errors_selected'); ?>: <?= $data['errors']; ?> / <?= $data['errors_total']; ?></p>
<?php endif; ?>
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<?php if (!empty($plugin)) {
echo Lang::get('plugin') . ': ' . Lang::get($plugin);
} else {
echo Lang::get('all_plugins');
} ?>&nbsp;&nbsp;<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>?severity=<?= urlencode($severity); ?>#errors"><?= Lang::get('all_plugins'); ?></a></li>
<li class="divider"></li>
<?php if(!empty($plugins)): ?>
<?php foreach ($plugins as $currentPlugin) : ?>
<li <?= ($currentPlugin === $plugin) ? 'class="active"' : ''; ?>>
<a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>?plugin=<?= urlencode($currentPlugin); ?>&severity=<?= urlencode($severity); ?>#errors">
<?= Lang::get($currentPlugin); ?>
</a>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<?php if ('' !== $severity) {
echo Lang::get('severity') . ': ' . Lang::get(BuildError::getSeverityName($severity));
} else {
echo Lang::get('all_severities');
} ?>&nbsp;&nbsp;<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>?plugin=<?= urlencode($plugin); ?>#errors"><?= Lang::get('all_severities'); ?></a></li>
<li class="divider"></li>
<?php if(!empty($severities)): ?>
<?php foreach ($severities as $currentSeverity) : ?>
<li <?= ($currentSeverity === $severity) ? 'class="active"' : ''; ?>>
<a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>?plugin=<?= urlencode($plugin); ?>&severity=<?= urlencode($currentSeverity); ?>#errors">
<?= Lang::get(BuildError::getSeverityName($currentSeverity)); ?>
</a>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
</div>
</div>
</div>
<?php endif; ?>
<table class="errors-table table table-hover">
<thead>
<tr>
@ -217,11 +277,13 @@ use PHPCensor\Model\Build;
<script src="<?php print APP_URL; ?>assets/js/build.js"></script>
<script>
var PER_PAGE = <?= $perPage; ?>;
var PAGE = <?= $page; ?>;
var PER_PAGE = <?= $perPage; ?>;
var PAGE = <?= $page; ?>;
var BUILD_PLUGIN = '<?= $plugin; ?>';
var BUILD_SEVERITY = '<?= $severity; ?>';
var ActiveBuild = new Build(<?php print $build->getId() ?>);
ActiveBuild.setupBuild(<?php print json_encode($data); ?>, <?php print json_encode($build->getFileLinkTemplate()); ?>);
var ActiveBuild = new Build(<?= $build->getId(); ?>);
ActiveBuild.setupBuild(<?= json_encode($data); ?>, <?= json_encode($build->getFileLinkTemplate()); ?>);
var url = document.location.toString();
if (url.match('#')) {
@ -235,8 +297,8 @@ use PHPCensor\Model\Build;
</script>
<?php
foreach ($plugins as $plugin) {
print '<script src="' . APP_URL . 'assets/js/build-plugins/' . $plugin . '"></script>' . PHP_EOL;
foreach ($uiPlugins as $uiPlugin) {
print '<script src="' . APP_URL . 'assets/js/build-plugins/' . $uiPlugin . '"></script>' . PHP_EOL;
}
?>