Split dashboard into widgets. Add build errors widget.

This commit is contained in:
Stepan Strelets 2017-11-06 00:34:11 +03:00
commit 11f58d7c2b
24 changed files with 793 additions and 328 deletions

View file

@ -1,153 +1,29 @@
<?php
use PHPCensor\Helper\Lang;
use PHPCensor\Model\Build;
/**
* @var Build[] $builds
* @var array $widgets
*/
$all_widgets = array_merge(array_keys($widgets['left']), array_keys($widgets['right']));
foreach($all_widgets as $widget) {
?><script src="<?= APP_URL ?>assets/js/dashboard-widgets/<?= $widget ?>.js" type="text/javascript"></script><?php
}
?>
<script>
var DASHBOARD = true;
</script>
<div class="row">
<div class="col-sm-5">
<?php foreach ($groups as $group): ?>
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php print $group['title']; ?></h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip" title="Collapse">
<i class="fa fa-minus"></i>
</button>
</div>
<?php foreach ($widgets['left'] as $widget => $params) { ?>
<div id="widget-<?= $widget ?>-container">
<div class="loader"></div>
</div>
<div class="box-body">
<?php print $group['summary']; ?>
</div>
</div>
<?php endforeach; ?>
<?php } ?>
</div>
<?php if (!empty($widgets['right'])) { ?>
<div class="col-sm-7 pull-left">
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php Lang::out('latest_builds'); ?></h3>
<?php foreach ($widgets['right'] as $widget => $params) { ?>
<div id="widget-<?= $widget ?>-container">
<div class="loader"></div>
</div>
<div class="box-body" id="timeline-box">
<ul class="timeline">
<?php $last = new \DateTime('-1 Year'); ?>
<?php
foreach ($builds as $build):
$environment = $build->getEnvironment();
$branches = $build->getExtra('branches');
switch ($build->getStatus()) {
case Build::STATUS_PENDING:
$updated = $build->getCreateDate();
$label = Lang::get('pending');
$color = 'blue';
break;
case Build::STATUS_RUNNING:
$updated = $build->getStartDate();
$label = Lang::get('running');
$color = 'yellow';
break;
case Build::STATUS_SUCCESS:
$updated = $build->getFinishDate();
$label = Lang::get('success');
$color = 'green';
break;
case Build::STATUS_FAILED:
$updated = $build->getFinishDate();
$label = Lang::get('failed');
$color = 'red';
break;
}
if (!$updated) {
$updated = $build->getCreateDate();
}
if ($updated->format('Y-m-d') != $last->format('Y-m-d')): $last = $updated;
?>
<li class="time-label">
<span class="bg-gray">
<?= $last->format('Y-m-d'); ?>
</span>
</li>
<?php endif; ?>
<!-- /.timeline-label -->
<!-- timeline item -->
<li>
<i class="fa fa-<?php print $build->getProject()->getIcon(); ?> bg-<?php print $color; ?>"></i>
<div class="timeline-item">
<span class="time"><i class="fa fa-clock-o"></i>
<?php
echo $updated->format('H:i:s');
if ($build->getStatus() != Build::STATUS_PENDING) {
echo ' &mdash; ' . $build->getDuration(); ?> <?= Lang::get('seconds');
}
?>
</span>
<h3 class="timeline-header">
<a href="<?= APP_URL; ?>project/view/<?= $build->getProjectId(); ?>">
<?= $build->getProject()->getTitle(); ?>
</a>
<span><?= $environment; ?></span>
&mdash;
<a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>">
Build #<?= $build->getId(); ?>
</a>
&mdash;
<?php Lang::out($build->getSourceHumanize()); ?>
</h3>
<div class="timeline-body">
<a href="<?= $build->getBranchLink();?>"><i class="fa fa-code-fork"></i> <?php echo $build->getBranch(); ?></a>
<?= $branches ? ' + '.implode(', ', $branches) : ''; ?>
<?php if ($tag = $build->getTag()): ?> /
<a href="<?= $build->getTagLink(); ?>" target="_blank">
<i class="fa fa-tag"></i> <?= $tag; ?>
</a>
<?php endif; ?>
<?php
if (!empty($build->getCommitId())) {
echo ' &mdash; ';
echo sprintf(
'<a href="%s" target="_blank">%s %s</a>',
$build->getCommitLink(),
substr($build->getCommitId(), 0, 7),
$build->getCommitterEmail() ? ('(' . $build->getCommitterEmail() . ')') : ''
);
if (!empty($build->getCommitMessage())) {
echo ' &mdash; ';
print $build->getCommitMessage();
}
}
?>
</div>
</div>
</li>
<!-- END timeline item -->
<?php endforeach; ?>
<li>
<i class="fa fa-clock-o"></i>
</li>
</ul>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
</div>

View file

@ -0,0 +1,15 @@
<?php foreach ($groups as $group): ?>
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php print $group['title']; ?></h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip" title="Collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php print $group['summary']; ?>
</div>
</div>
<?php endforeach; ?>

View file

@ -0,0 +1,13 @@
<?php
use PHPCensor\Helper\Lang;
?>
<div class="box">
<div class="box-header">
<h3 class="box-title"><?= Lang::out('projects_with_build_errors') ?></h3>
</div>
<div class="box-body" id="dashboard-build-errors">
<?= $projects ?>
</div>
</div>

View file

@ -0,0 +1,157 @@
<?php
use PHPCensor\Helper\Lang;
use PHPCensor\Model\Build;
/**
* @var Build[] $builds
*/
foreach($builds as $project_id => $project_envs):
if (!isset($projects[$project_id])) {
echo '<!-- project '.$project_id.' not set -->';
continue;
}
$project = $projects[$project_id];
foreach($project_envs as $environment => $project_env):
$statuses = [];
$failures = 0;
$subcls = 'gray';
$cls = '';
$success = null;
$failure = null;
// Get the most recent build status to determine the main block colour.
$last_build = $project_env['latest'][0];
$status = $last_build->getStatus();
switch($status) {
case 0:
$subcls = 'blue';
break;
case 1:
$subcls = 'yellow';
break;
case 2:
$subcls = 'green';
break;
case 3:
$subcls = 'red';
break;
}
// Use the last 5 builds to determine project health:
$failures = 0;
foreach ($project_env['latest'] as $build) {
switch ($build->getStatus()) {
case 0:
$statuses[] = 'pending';
break;
case 1:
$statuses[] = 'running';
break;
case 2:
$statuses[] = 'ok';
$success = is_null($success) && !is_null($build->getFinishDate()) ? $build->getFinishDate()->format('Y-m-d H:i:s') : $success;
break;
case 3:
$failures++;
$statuses[] = 'failed';
$failure = is_null($failure) && !is_null($build->getFinishDate()) ? $build->getFinishDate()->format('Y-m-d H:i:s') : $failure;
break;
}
}
$buildCount = count($project_env['latest']);
$lastSuccess = $project_env['success'];
$lastFailure = $project_env['failed'];
$message = Lang::get('no_builds_yet');
$shortMessage = Lang::get('no_builds_yet');
if ($buildCount > 0) {
if ($failures > 0) {
$shortMessage = Lang::get('x_of_x_failed_short', $failures, $buildCount);
$message = Lang::get('x_of_x_failed', $failures, $buildCount);
if (!is_null($lastSuccess) && !is_null($lastSuccess->getFinishDate())) {
$message .= Lang::get('last_successful_build', $lastSuccess->getFinishDate()->format('Y-m-d H:i:s'));
} else {
$message .= Lang::get('never_built_successfully');
}
} else {
$message = Lang::get('all_builds_passed', $buildCount);
$shortMessage = Lang::get('all_builds_passed_short', $buildCount, $buildCount);
if (!is_null($lastFailure) && !is_null($lastFailure->getFinishDate())) {
$message .= Lang::get('last_failed_build', $lastFailure->getFinishDate()->format('Y-m-d H:i:s'));
} else {
$message .= Lang::get('never_failed_build');
}
}
}
?>
<div class="project-box">
<div class="small-box small-box-full bg-<?= $subcls; ?>">
<div class="inner">
<h3>
<a href="<?= APP_URL; ?>project/view/<?= $project->getId(); ?>">
<?= $project->getTitle(); ?>
</a>
<?php if (!empty($environment)) { ?>
<sup title="<?php Lang::out('environment'); ?>"><?= $environment ?></sup>
<?php } ?>
</h3>
<p>
<?= $message; ?>
</p>
</div>
<div class="icon">
<i class="fa fa-<?php print $project->getIcon(); ?>"></i>
</div>
<a href="<?= APP_URL; ?>project/view/<?= $project->getId(); ?>" class="small-box-footer small-box-footer-project">
<div class="pull-left" style="margin-left: 10px">
<?php if ($project->getAllowPublicStatus()): ?>
<i class="fa fa-unlock"></i>
<?php else: ?>
<i class="fa fa-lock"></i>
<?php endif; ?>
</div>
<?php Lang::out('view_project'); ?> <i class="fa fa-arrow-circle-right"></i>
</a>
<?php for ($idx=0; $idx < 5; $idx++) {
if (empty($project_env['latest'][$idx])) {
echo '<span class="small-box-footer-build small-box-footer bg-gray"><i class="fa fa-minus"></i></span>';
} else {
$build = $project_env['latest'][$idx];
$link = APP_URL . 'build/view/' . $build->id;
switch ($build->getStatus()) {
case 0:
$class = 'bg-blue';
$icon = 'fa-clock-o';
break;
case 1:
$class = 'bg-yellow';
$icon = 'fa-cogs';
break;
case 2:
$class = 'bg-green';
$icon = 'fa-check';
break;
case 3:
$class = 'bg-red';
$icon = 'fa-times';
break;
}
echo '<a href="' . $link .'" class="small-box-footer-build small-box-footer ' . $class . '"><i class="fa ' . $icon . '"></i></a>';
}
} ?>
<div style="clear: both;"></div>
</div>
</div>
<?php endforeach; ?>
<?php endforeach; ?>

View file

@ -0,0 +1,13 @@
<?php
use PHPCensor\Helper\Lang;
?>
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php Lang::out('latest_builds'); ?></h3>
</div>
<div class="box-body" id="timeline-box">
<?= $timeline ?>
</div>
</div>