UI plugins, including quality trend chart, logs and lines of code. Some UI tweaks.
This commit is contained in:
parent
a634f6086b
commit
b33189e08e
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
.idea
|
||||
vendor/
|
||||
composer.lock
|
||||
composer.phar
|
||||
config.php
|
||||
.DS_Store
|
||||
|
|
|
@ -74,6 +74,11 @@ class Builder
|
|||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $lastOutput;
|
||||
|
||||
/**
|
||||
* An array of key => value pairs that will be used for
|
||||
* interpolation and environment variables
|
||||
|
@ -83,6 +88,11 @@ class Builder
|
|||
*/
|
||||
protected $interpolation_vars = array();
|
||||
|
||||
/**
|
||||
* @var \PHPCI\Store\BuildStore
|
||||
*/
|
||||
protected $store;
|
||||
|
||||
/**
|
||||
* Set up the builder.
|
||||
* @param \PHPCI\Model\Build
|
||||
|
@ -214,17 +224,24 @@ class Builder
|
|||
|
||||
$this->log('Executing: ' . $command, ' ');
|
||||
|
||||
$output = '';
|
||||
$status = 0;
|
||||
exec($command, $output, $status);
|
||||
exec($command, $this->lastOutput, $status);
|
||||
|
||||
if (!empty($output) && ($this->verbose || $status != 0)) {
|
||||
$this->log($output, ' ');
|
||||
if (!empty($this->lastOutput) && ($this->verbose || $status != 0)) {
|
||||
$this->log($this->lastOutput, ' ');
|
||||
}
|
||||
|
||||
return ($status == 0) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output from the last command run.
|
||||
*/
|
||||
public function getLastOutput()
|
||||
{
|
||||
return implode(PHP_EOL, $this->lastOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the build log.
|
||||
* @param string|string[]
|
||||
|
@ -433,4 +450,13 @@ class Builder
|
|||
$this->log('Removing build.');
|
||||
shell_exec(sprintf('rm -Rf "%s"', $this->buildPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store build meta data
|
||||
*/
|
||||
public function storeBuildMeta($key, $value)
|
||||
{
|
||||
$value = json_encode($value);
|
||||
$this->store->setMeta($this->build->getProjectId(), $this->build->getId(), $key, $value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,28 @@ class BuildController extends \PHPCI\Controller
|
|||
public function view($buildId)
|
||||
{
|
||||
$build = $this->_buildStore->getById($buildId);
|
||||
$this->view->plugins = $this->getUiPlugins();
|
||||
$this->view->build = $build;
|
||||
$this->view->data = $this->getBuildData($buildId);
|
||||
}
|
||||
|
||||
protected function getUiPlugins()
|
||||
{
|
||||
$rtn = array();
|
||||
$path = APPLICATION_PATH . 'public/assets/js/build-plugins/';
|
||||
$dir = opendir($path);
|
||||
|
||||
while ($item = readdir($dir)) {
|
||||
if (substr($item, 0, 1) == '.' || substr($item, -3) != '.js') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rtn[] = $item;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX call to get build data:
|
||||
*/
|
||||
|
@ -43,6 +61,23 @@ class BuildController extends \PHPCI\Controller
|
|||
die($this->getBuildData($buildId));
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX call to get build meta:
|
||||
*/
|
||||
public function meta($buildId)
|
||||
{
|
||||
$build = $this->_buildStore->getById($buildId);
|
||||
$key = $this->getParam('key', null);
|
||||
$numBuilds = $this->getParam('num_builds', 1);
|
||||
$data = null;
|
||||
|
||||
if ($key && $build) {
|
||||
$data = $this->_buildStore->getMeta($key, $build->getProjectId(), $buildId, $numBuilds);
|
||||
}
|
||||
|
||||
die(json_encode($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get build data from database and json encode it:
|
||||
*/
|
||||
|
|
|
@ -579,4 +579,16 @@ class BuildBase extends Model
|
|||
{
|
||||
return $this->setProjectId($value->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BuildMeta models by BuildId for this Build.
|
||||
*
|
||||
* @uses \PHPCI\Store\BuildMetaStore::getByBuildId()
|
||||
* @uses \PHPCI\Model\BuildMeta
|
||||
* @return \PHPCI\Model\BuildMeta[]
|
||||
*/
|
||||
public function getBuildBuildMetas()
|
||||
{
|
||||
return \b8\Store\Factory::getStore('BuildMeta')->getByBuildId($this->getId());
|
||||
}
|
||||
}
|
||||
|
|
293
PHPCI/Model/Base/BuildMetaBase.php
Normal file
293
PHPCI/Model/Base/BuildMetaBase.php
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* BuildMeta base model for table: build_meta
|
||||
*/
|
||||
|
||||
namespace PHPCI\Model\Base;
|
||||
|
||||
use b8\Model;
|
||||
|
||||
/**
|
||||
* BuildMeta Base Model
|
||||
*/
|
||||
class BuildMetaBase extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $sleepable = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName = 'build_meta';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $modelName = 'BuildMeta';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array(
|
||||
'id' => null,
|
||||
'build_id' => null,
|
||||
'key' => null,
|
||||
'value' => null,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $getters = array(
|
||||
'id' => 'getId',
|
||||
'build_id' => 'getBuildId',
|
||||
'key' => 'getKey',
|
||||
'value' => 'getValue',
|
||||
'Build' => 'getBuild',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $setters = array(
|
||||
'id' => 'setId',
|
||||
'build_id' => 'setBuildId',
|
||||
'key' => 'setKey',
|
||||
'value' => 'setValue',
|
||||
'Build' => 'setBuild',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $columns = array(
|
||||
'id' => array(
|
||||
'type' => 'int',
|
||||
'length' => '10',
|
||||
'primary_key' => true,
|
||||
'auto_increment' => true,
|
||||
),
|
||||
'build_id' => array(
|
||||
'type' => 'int',
|
||||
'length' => '11',
|
||||
),
|
||||
'key' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => '255',
|
||||
),
|
||||
'value' => array(
|
||||
'type' => 'text',
|
||||
'length' => '',
|
||||
'nullable' => true,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $indexes = array(
|
||||
'PRIMARY' => array('unique' => true, 'columns' => 'id'),
|
||||
'idx_meta_id' => array('unique' => true, 'columns' => 'build_id, key'),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $foreignKeys = array(
|
||||
'fk_meta_build_id' => array(
|
||||
'local_col' => 'build_id',
|
||||
'update' => 'CASCADE',
|
||||
'delete' => 'CASCADE',
|
||||
'table' => 'build',
|
||||
'col' => 'id'
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of Id / id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
$rtn = $this->data['id'];
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of BuildId / build_id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBuildId()
|
||||
{
|
||||
$rtn = $this->data['build_id'];
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of Key / key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
$rtn = $this->data['key'];
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of Value / value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
$rtn = $this->data['value'];
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of Id / id.
|
||||
*
|
||||
* Must not be null.
|
||||
* @param $value int
|
||||
*/
|
||||
public function setId($value)
|
||||
{
|
||||
$this->_validateNotNull('Id', $value);
|
||||
$this->_validateInt('Id', $value);
|
||||
if ($this->data['id'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['id'] = $value;
|
||||
|
||||
$this->_setModified('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of BuildId / build_id.
|
||||
*
|
||||
* Must not be null.
|
||||
* @param $value int
|
||||
*/
|
||||
public function setBuildId($value)
|
||||
{
|
||||
$this->_validateNotNull('BuildId', $value);
|
||||
$this->_validateInt('BuildId', $value);
|
||||
if ($this->data['build_id'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['build_id'] = $value;
|
||||
|
||||
$this->_setModified('build_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of Key / key.
|
||||
*
|
||||
* Must not be null.
|
||||
* @param $value string
|
||||
*/
|
||||
public function setKey($value)
|
||||
{
|
||||
$this->_validateNotNull('Key', $value);
|
||||
$this->_validateString('Key', $value);
|
||||
if ($this->data['key'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['key'] = $value;
|
||||
|
||||
$this->_setModified('key');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of Value / value.
|
||||
*
|
||||
* @param $value string
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
|
||||
$this->_validateString('Value', $value);
|
||||
if ($this->data['value'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['value'] = $value;
|
||||
|
||||
$this->_setModified('value');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Build model for this BuildMeta by Id.
|
||||
*
|
||||
* @uses \PHPCI\Store\BuildStore::getById()
|
||||
* @uses \PHPCI\Model\Build
|
||||
* @return \PHPCI\Model\Build
|
||||
*/
|
||||
public function getBuild()
|
||||
{
|
||||
$key = $this->getBuildId();
|
||||
|
||||
if (empty($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cacheKey = 'Cache.Build.' . $key;
|
||||
$rtn = $this->cache->get($cacheKey, null);
|
||||
|
||||
if (empty($rtn)) {
|
||||
$rtn = \b8\Store\Factory::getStore('Build')->getById($key);
|
||||
$this->cache->set($cacheKey, $rtn);
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Build - Accepts an ID, an array representing a Build or a Build model.
|
||||
*
|
||||
* @param $value mixed
|
||||
*/
|
||||
public function setBuild($value)
|
||||
{
|
||||
// Is this an instance of Build?
|
||||
if ($value instanceof \PHPCI\Model\Build) {
|
||||
return $this->setBuildObject($value);
|
||||
}
|
||||
|
||||
// Is this an array representing a Build item?
|
||||
if (is_array($value) && !empty($value['id'])) {
|
||||
return $this->setBuildId($value['id']);
|
||||
}
|
||||
|
||||
// Is this a scalar value representing the ID of this foreign key?
|
||||
return $this->setBuildId($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Build - Accepts a Build model.
|
||||
*
|
||||
* @param $value \PHPCI\Model\Build
|
||||
*/
|
||||
public function setBuildObject(\PHPCI\Model\Build $value)
|
||||
{
|
||||
return $this->setBuildId($value->getId());
|
||||
}
|
||||
}
|
|
@ -34,11 +34,11 @@ class ProjectBase extends Model
|
|||
protected $data = array(
|
||||
'id' => null,
|
||||
'title' => null,
|
||||
'access_information' => null,
|
||||
'reference' => null,
|
||||
'git_key' => null,
|
||||
'type' => null,
|
||||
'token' => null,
|
||||
'access_information' => null,
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -50,8 +50,8 @@ class ProjectBase extends Model
|
|||
'reference' => 'getReference',
|
||||
'git_key' => 'getGitKey',
|
||||
'type' => 'getType',
|
||||
'access_information' => 'getAccessInformation',
|
||||
'token' => 'getToken',
|
||||
'access_information' => 'getAccessInformation',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -63,8 +63,8 @@ class ProjectBase extends Model
|
|||
'reference' => 'setReference',
|
||||
'git_key' => 'setGitKey',
|
||||
'type' => 'setType',
|
||||
'access_information' => 'setAccessInformation',
|
||||
'token' => 'setToken',
|
||||
'access_information' => 'setAccessInformation',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -85,10 +85,6 @@ class ProjectBase extends Model
|
|||
'type' => 'varchar',
|
||||
'length' => '250',
|
||||
),
|
||||
'access_information' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => '250',
|
||||
),
|
||||
'git_key' => array(
|
||||
'type' => 'text',
|
||||
'length' => '',
|
||||
|
@ -102,6 +98,10 @@ class ProjectBase extends Model
|
|||
'length' => '50',
|
||||
'nullable' => true,
|
||||
),
|
||||
'access_information' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => '250',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -157,19 +157,6 @@ class ProjectBase extends Model
|
|||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of Domain / domain.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessInformation()
|
||||
{
|
||||
$rtn = unserialize($this->data['access_information']);
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of GitKey / git_key.
|
||||
*
|
||||
|
@ -209,6 +196,19 @@ class ProjectBase extends Model
|
|||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of AccessInformation / access_information.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessInformation()
|
||||
{
|
||||
$rtn = $this->data['access_information'];
|
||||
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of Id / id.
|
||||
*
|
||||
|
@ -266,25 +266,6 @@ class ProjectBase extends Model
|
|||
$this->_setModified('reference');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of Domain / domain.
|
||||
*
|
||||
* Must not be null.
|
||||
* @param $value string
|
||||
*/
|
||||
public function setAccessInformation($value)
|
||||
{
|
||||
$this->_validateNotNull('AccessInformation', $value);
|
||||
$this->_validateString('AccessInformation', $value);
|
||||
if ($this->data['access_information'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['access_information'] = $value;
|
||||
|
||||
$this->_setModified('access_information');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of GitKey / git_key.
|
||||
*
|
||||
|
@ -341,6 +322,25 @@ class ProjectBase extends Model
|
|||
$this->_setModified('token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of AccessInformation / access_information.
|
||||
*
|
||||
* Must not be null.
|
||||
* @param $value string
|
||||
*/
|
||||
public function setAccessInformation($value)
|
||||
{
|
||||
$this->_validateNotNull('AccessInformation', $value);
|
||||
$this->_validateString('AccessInformation', $value);
|
||||
if ($this->data['access_information'] == $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['access_information'] = $value;
|
||||
|
||||
$this->_setModified('access_information');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Build models by ProjectId for this Project.
|
||||
*
|
||||
|
|
20
PHPCI/Model/BuildMeta.php
Normal file
20
PHPCI/Model/BuildMeta.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* BuildMeta model for table: build_meta
|
||||
*/
|
||||
|
||||
namespace PHPCI\Model;
|
||||
|
||||
require_once(APPLICATION_PATH . 'PHPCI/Model/Base/BuildMetaBase.php');
|
||||
|
||||
use PHPCI\Model\Base\BuildMetaBase;
|
||||
|
||||
/**
|
||||
* BuildMeta Model
|
||||
* @uses PHPCI\Model\Base\BuildMetaBase
|
||||
*/
|
||||
class BuildMeta extends BuildMetaBase
|
||||
{
|
||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
||||
}
|
|
@ -106,6 +106,20 @@ class PhpCodeSniffer implements \PHPCI\Plugin
|
|||
}
|
||||
|
||||
$cmd = PHPCI_BIN_DIR . 'phpcs %s %s %s %s %s "%s"';
|
||||
return $this->phpci->executeCommand($cmd, $standard, $suffixes, $ignore, $tab_width, $encoding, $this->phpci->buildPath . $this->path);
|
||||
$success = $this->phpci->executeCommand($cmd, $standard, $suffixes, $ignore, $tab_width, $encoding, $this->phpci->buildPath . $this->path);
|
||||
|
||||
$output = $this->phpci->getLastOutput();
|
||||
|
||||
$matches = array();
|
||||
if (preg_match_all('/WARNING/', $output, $matches)) {
|
||||
$this->phpci->storeBuildMeta('phpcs-warnings', count($matches[0]));
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
if (preg_match_all('/ERROR/', $output, $matches)) {
|
||||
$this->phpci->storeBuildMeta('phpcs-errors', count($matches[0]));
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ class PhpCpd implements \PHPCI\Plugin
|
|||
$ignore = implode('', $ignore);
|
||||
}
|
||||
|
||||
return $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phpcpd %s "%s"', $ignore, $this->phpci->buildPath.$this->path);
|
||||
$success = $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phpcpd %s "%s"', $ignore, $this->phpci->buildPath.$this->path);
|
||||
|
||||
print $this->phpci->getLastOutput();
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,18 @@ class PhpLoc implements \PHPCI\Plugin
|
|||
$ignore = implode('', $ignore);
|
||||
}
|
||||
|
||||
return $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phploc %s "%s"', $ignore, $this->phpci->buildPath);
|
||||
$success = $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phploc %s "%s"', $ignore, $this->phpci->buildPath);
|
||||
$output = $this->phpci->getLastOutput();
|
||||
|
||||
if (preg_match_all('/\((LOC|CLOC|NCLOC|LLOC)\)\s+([0-9]+)/', $output, $matches)) {
|
||||
$data = array();
|
||||
foreach ($matches[1] as $k => $v) {
|
||||
$data[$v] = (int)$matches[2][$k];
|
||||
}
|
||||
|
||||
$this->phpci->storeBuildMeta('phploc', $data);
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
|
@ -83,6 +83,10 @@ class PhpMessDetector implements \PHPCI\Plugin
|
|||
}
|
||||
|
||||
$cmd = PHPCI_BIN_DIR . 'phpmd "%s" text %s %s %s';
|
||||
return $this->phpci->executeCommand($cmd, $this->phpci->buildPath . $this->path, implode(',', $this->rules), $ignore, $suffixes);
|
||||
$success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath . $this->path, implode(',', $this->rules), $ignore, $suffixes);
|
||||
$errors = count(array_filter(explode(PHP_EOL, $this->phpci->getLastOutput())));
|
||||
$this->phpci->storeBuildMeta('phpmd-warnings', $errors);
|
||||
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
|
86
PHPCI/Store/Base/BuildMetaStoreBase.php
Normal file
86
PHPCI/Store/Base/BuildMetaStoreBase.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* BuildMeta base store for table: build_meta
|
||||
*/
|
||||
|
||||
namespace PHPCI\Store\Base;
|
||||
|
||||
use b8\Store;
|
||||
|
||||
/**
|
||||
* BuildMeta Base Store
|
||||
*/
|
||||
class BuildMetaStoreBase extends Store
|
||||
{
|
||||
protected $tableName = 'build_meta';
|
||||
protected $modelName = '\PHPCI\Model\BuildMeta';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
public function getByPrimaryKey($value, $useConnection = 'read')
|
||||
{
|
||||
return $this->getById($value, $useConnection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getById($value, $useConnection = 'read')
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
|
||||
}
|
||||
|
||||
$query = 'SELECT * FROM build_meta WHERE id = :id LIMIT 1';
|
||||
$stmt = \b8\Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':id', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
return new \PHPCI\Model\BuildMeta($data);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getByBuildId($value, $limit = null, $useConnection = 'read')
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
|
||||
}
|
||||
|
||||
$add = '';
|
||||
|
||||
if ($limit) {
|
||||
$add .= ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
$query = 'SELECT COUNT(*) AS cnt FROM build_meta WHERE build_id = :build_id' . $add;
|
||||
$stmt = \b8\Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':build_id', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$res = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
$count = (int)$res['cnt'];
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
$query = 'SELECT * FROM build_meta WHERE build_id = :build_id' . $add;
|
||||
$stmt = \b8\Database::getConnection('read')->prepare($query);
|
||||
$stmt->bindValue(':build_id', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
$map = function ($item) {
|
||||
return new \PHPCI\Model\BuildMeta($item);
|
||||
};
|
||||
$rtn = array_map($map, $res);
|
||||
|
||||
return array('items' => $rtn, 'count' => $count);
|
||||
} else {
|
||||
return array('items' => array(), 'count' => 0);
|
||||
}
|
||||
}
|
||||
}
|
20
PHPCI/Store/BuildMetaStore.php
Normal file
20
PHPCI/Store/BuildMetaStore.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* BuildMeta store for table: build_meta
|
||||
*/
|
||||
|
||||
namespace PHPCI\Store;
|
||||
|
||||
require_once(APPLICATION_PATH . 'PHPCI/Store/Base/BuildMetaStoreBase.php');
|
||||
|
||||
use PHPCI\Store\Base\BuildMetaStoreBase;
|
||||
|
||||
/**
|
||||
* BuildMeta Store
|
||||
* @uses PHPCI\Store\Base\BuildMetaStoreBase
|
||||
*/
|
||||
class BuildMetaStore extends BuildMetaStoreBase
|
||||
{
|
||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
||||
}
|
|
@ -47,4 +47,52 @@ class BuildStore extends BuildStoreBase
|
|||
return array('items' => array(), 'count' => 0);
|
||||
}
|
||||
}
|
||||
|
||||
public function getMeta($key, $projectId, $buildId = null, $numResults = 1)
|
||||
{
|
||||
$and = $numResults > 1 ? ' AND (`build_id` <= :buildId) ' : ' AND (`build_id` = :buildId) ';
|
||||
$query = 'SELECT `build_id`, `key`, `value` FROM `build_meta` WHERE `key` = :key AND `project_id` = :projectId ' . $and . ' ORDER BY id DESC LIMIT :numResults';
|
||||
|
||||
$stmt = \b8\Database::getConnection('read')->prepare($query);
|
||||
$stmt->bindValue(':key', $key, \PDO::PARAM_STR);
|
||||
$stmt->bindValue(':projectId', (int)$projectId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':buildId', (int)$buildId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':numResults', (int)$numResults, \PDO::PARAM_INT);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$rtn = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
$rtn = array_reverse($rtn);
|
||||
$rtn = array_map(function($item) {
|
||||
$item['value'] = json_decode($item['value'], true);
|
||||
return $item;
|
||||
}, $rtn);
|
||||
|
||||
if (!count($rtn)) {
|
||||
return null;
|
||||
} else {
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function setMeta($projectId, $buildId, $key, $value)
|
||||
{
|
||||
$query = 'REPLACE INTO build_meta (project_id, build_id, `key`, `value`) VALUES (:projectId, :buildId, :key, :value)';
|
||||
|
||||
$stmt = \b8\Database::getConnection('read')->prepare($query);
|
||||
$stmt->bindValue(':key', $key, \PDO::PARAM_STR);
|
||||
$stmt->bindValue(':projectId', (int)$projectId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':buildId', (int)$buildId, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':value', $value, \PDO::PARAM_STR);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,68 +16,27 @@
|
|||
<li><a href="#" id="delete-build"><i class="icon-trash"></i> Delete Build</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
<table class="table table-striped table-bordered" style="margin-top: 20px">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">Plugin Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="plugins">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-9">
|
||||
<div id="status"></div>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 33.3%">Build Created</th>
|
||||
<th style="width: 33.3%">Build Started</th>
|
||||
<th style="width: 33.3%">Build Finished</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td id="created"></td>
|
||||
<td id="started"></td>
|
||||
<td id="finished"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Build Log</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><pre style="height: 300px; overflow-y: auto;" id="log"></pre></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="plugins"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.initial = <?php print $data; ?>;
|
||||
var PHPCI = new PHPCIObject(<?php print $build->getId() ?>);
|
||||
PHPCI.buildData = <?php print $data; ?>;
|
||||
</script>
|
||||
|
||||
<?php if($build->getStatus() == 0 || $build->getStatus() == 1 || true): ?>
|
||||
setInterval(function()
|
||||
{
|
||||
$.getJSON('<?= PHPCI_URL ?>build/data/<?php print $build->getId(); ?>', updateBuildView);
|
||||
}, 10000);
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
foreach ($plugins as $plugin) {
|
||||
print '<script src="'.PHPCI_URL.'assets/js/build-plugins/' . $plugin . '"></script>';
|
||||
}
|
||||
?>
|
||||
|
||||
$(function() {
|
||||
updateBuildView(window.initial);
|
||||
|
||||
$('#delete-build').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
confirmDelete("<?= PHPCI_URL ?>build/delete/<?php print $build->getId(); ?>");
|
||||
});
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
PHPCI.renderPlugins();
|
||||
});
|
||||
</script>
|
|
@ -41,7 +41,8 @@
|
|||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<h3>Project Overview</h3>
|
||||
<div class="box">
|
||||
<h3 class="title">Project Overview</h3>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -57,8 +58,10 @@
|
|||
<?php print $summary; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3>Last 5 Builds</h3>
|
||||
<div class="box">
|
||||
<h3 class="title">Last 5 Builds</h3>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -75,6 +78,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<div class="box">
|
||||
<?php print $form; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<div class="box">
|
||||
<?php print $form; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -9,8 +9,15 @@
|
|||
<link href='//fonts.googleapis.com/css?family=Roboto:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="<?= PHPCI_URL ?>assets/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="<?= PHPCI_URL ?>assets/css/phpci.css">
|
||||
|
||||
<script>window.PHPCI_URL = <?php print json_encode(PHPCI_URL) ?></script>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
|
||||
|
||||
<script src="<?= PHPCI_URL ?>assets/js/bootstrap.min.js"></script>
|
||||
<script src="<?= PHPCI_URL ?>assets/js/jqueryui.js"></script>
|
||||
<script src="<?= PHPCI_URL ?>assets/js/class.js"></script>
|
||||
<script src="<?= PHPCI_URL ?>assets/js/phpci.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
1663
composer.lock
generated
Normal file
1663
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
body
|
||||
{
|
||||
background: #246;
|
||||
background: #f9f9f9;
|
||||
font-family: Roboto, Arial, Sans-Serif;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
|
@ -9,8 +9,7 @@ body
|
|||
|
||||
#content
|
||||
{
|
||||
background: #fff;
|
||||
border: 10px solid #369;
|
||||
-border: 10px solid #369;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
@ -50,7 +49,6 @@ td .label {
|
|||
|
||||
#title
|
||||
{
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: -10px -10px 15px -10px;
|
||||
padding: 10px;
|
||||
|
@ -93,3 +91,40 @@ h3
|
|||
.navbar-brand {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.box {
|
||||
background: #fff;
|
||||
box-shadow: 0 0 5px rgba(0,0,0,0.1);
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
}
|
||||
.box .title {
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: move;
|
||||
font-size: 1.2em;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.box .box-content {
|
||||
}
|
||||
|
||||
.box .box-content table, .box .box-content pre {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.box .box-content pre {
|
||||
background: #fff;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.ui-sortable-placeholder {
|
||||
border: 1px dashed #ccc;
|
||||
background: #ffe;
|
||||
height: 100px;
|
||||
margin-bottom: 15px;
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
.ui-sortable-placeholder * { visibility: hidden; }
|
||||
|
||||
.ui-plugin { padding-top: 15px; }
|
65
public/assets/js/build-plugins/loc.js
Normal file
65
public/assets/js/build-plugins/loc.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
var locPlugin = PHPCI.UiPlugin.extend({
|
||||
id: 'build-lines-chart',
|
||||
css: 'col-lg-6 col-md-6 col-sm-12 col-xs-12',
|
||||
title: 'Lines of Code',
|
||||
lastData: null,
|
||||
displayOnUpdate: false,
|
||||
|
||||
register: function() {
|
||||
var self = this;
|
||||
var query = PHPCI.registerQuery('phploc-lines', -1, {num_builds: 10, key: 'phploc'})
|
||||
|
||||
$(window).on('phploc-lines', function(data) {
|
||||
self.onUpdate(data);
|
||||
});
|
||||
|
||||
$(window).on('build-updated', function(data) {
|
||||
if (data.queryData.status > 1) {
|
||||
self.displayOnUpdate = true;
|
||||
query();
|
||||
}
|
||||
});
|
||||
|
||||
google.load("visualization", "1", {packages:["corechart"]});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return $('<div id="phploc-lines"></div>').text('This chart will display once the build has completed.');
|
||||
},
|
||||
|
||||
onUpdate: function(e) {
|
||||
this.lastData = e.queryData;
|
||||
|
||||
if (this.displayOnUpdate) {
|
||||
this.displayChart();
|
||||
}
|
||||
},
|
||||
|
||||
displayChart: function() {
|
||||
var build = this.lastData;
|
||||
|
||||
if (!build || !build.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#phploc-lines').empty().animate({height: '275px'});
|
||||
|
||||
var data = [["Build", "Lines", "Comment Lines", "Non-Comment Lines", "Logical Lines"]];
|
||||
for (var idx in build) {
|
||||
data.push(['Build ' + build[idx].build_id, parseInt(build[idx].value.LOC), parseInt(build[idx].value.CLOC), parseInt(build[idx].value.NCLOC), parseInt(build[idx].value.LLOC)]);
|
||||
}
|
||||
|
||||
var data = google.visualization.arrayToDataTable(data);
|
||||
|
||||
var options = {
|
||||
hAxis: {title: 'Builds'},
|
||||
vAxis: {title: 'Lines'},
|
||||
backgroundColor: { fill: 'transparent' }
|
||||
};
|
||||
|
||||
var chart = new google.visualization.LineChart(document.getElementById('phploc-lines'));
|
||||
chart.draw(data, options);
|
||||
}
|
||||
});
|
||||
|
||||
PHPCI.registerPlugin(new locPlugin());
|
23
public/assets/js/build-plugins/log.js
Normal file
23
public/assets/js/build-plugins/log.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
var logPlugin = PHPCI.UiPlugin.extend({
|
||||
id: 'build-log',
|
||||
css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12',
|
||||
title: 'Build Log',
|
||||
|
||||
init: function(){
|
||||
this._super();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var container = $('<pre></pre>');
|
||||
container.css({height: '300px', 'overflow-y': 'auto'});
|
||||
container.html(PHPCI.buildData.log);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
onUpdate: function(e) {
|
||||
$('#build-log pre').html(e.queryData.log);
|
||||
}
|
||||
});
|
||||
|
||||
PHPCI.registerPlugin(new logPlugin());
|
37
public/assets/js/build-plugins/time.js
Normal file
37
public/assets/js/build-plugins/time.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
var timePlugin = PHPCI.UiPlugin.extend({
|
||||
id: 'build-time',
|
||||
css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12',
|
||||
title: null,
|
||||
box: true,
|
||||
|
||||
init: function(){
|
||||
this._super();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return '<table class="table table-striped table-bordered">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
'<th style="width: 33.3%">Build Created</th>' +
|
||||
'<th style="width: 33.3%">Build Started</th>' +
|
||||
'<th style="width: 33.3%">Build Finished</th>' +
|
||||
'</tr>' +
|
||||
'</thead>' +
|
||||
'<tbody>' +
|
||||
'<tr>' +
|
||||
'<td id="created">' + PHPCI.buildData.created + '</td>' +
|
||||
'<td id="started">' + PHPCI.buildData.started + '</td>' +
|
||||
'<td id="finished">' + PHPCI.buildData.finished + '</td>' +
|
||||
'</tr>' +
|
||||
'</tbody>' +
|
||||
'</table>';
|
||||
},
|
||||
|
||||
onUpdate: function(build) {
|
||||
$('#created').text(build.created);
|
||||
$('#started').text(build.started);
|
||||
$('#finished').text(build.finished);
|
||||
}
|
||||
});
|
||||
|
||||
PHPCI.registerPlugin(new timePlugin());
|
98
public/assets/js/build-plugins/warnings.js
Normal file
98
public/assets/js/build-plugins/warnings.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
var plugin = PHPCI.UiPlugin.extend({
|
||||
id: 'build-warnings-chart',
|
||||
css: 'col-lg-6 col-md-6 col-sm-12 col-xs-12',
|
||||
title: 'Quality Trend',
|
||||
data: {},
|
||||
keys: null,
|
||||
displayOnUpdate: false,
|
||||
|
||||
register: function() {
|
||||
var self = this;
|
||||
var query1 = PHPCI.registerQuery('phpmd-warnings', -1, {num_builds: 10, key: 'phpmd-warnings'})
|
||||
var query2 = PHPCI.registerQuery('phpcs-warnings', -1, {num_builds: 10, key: 'phpcs-warnings'})
|
||||
var query3 = PHPCI.registerQuery('phpcs-errors', -1, {num_builds: 10, key: 'phpcs-errors'})
|
||||
|
||||
$(window).on('phpmd-warnings phpcs-warnings phpcs-errors', function(data) {
|
||||
self.onUpdate(data);
|
||||
});
|
||||
|
||||
$(window).on('build-updated', function(data) {
|
||||
if (data.queryData.status > 1) {
|
||||
self.displayOnUpdate = true;
|
||||
query1();
|
||||
query2();
|
||||
query3();
|
||||
}
|
||||
});
|
||||
|
||||
google.load("visualization", "1", {packages:["corechart"]});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return $('<div id="build-warnings"></div>').text('This chart will display once the build has completed.');
|
||||
},
|
||||
|
||||
onUpdate: function(e) {
|
||||
var self = this;
|
||||
var build = e.queryData;
|
||||
|
||||
if (!build || !build.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i in build) {
|
||||
var buildId = build[i]['build_id'];
|
||||
var metaKey = build[i]['key'];
|
||||
var metaVal = build[i]['value'];
|
||||
|
||||
if (!self.data[buildId]) {
|
||||
self.data[buildId] = {};
|
||||
}
|
||||
|
||||
self.data[buildId][metaKey] = metaVal;
|
||||
self.keys = Object.keys(self.data[buildId]);
|
||||
}
|
||||
|
||||
if (self.displayOnUpdate) {
|
||||
self.displayChart();
|
||||
}
|
||||
},
|
||||
|
||||
displayChart: function() {
|
||||
var self = this;
|
||||
|
||||
$('#build-warnings').empty().animate({height: '275px'});
|
||||
|
||||
var titles = ['Build'];
|
||||
var keys = self.keys;
|
||||
|
||||
for (var i in keys) {
|
||||
var t = {'phpmd-warnings': 'PHPMD Warnings', 'phpcs-warnings': 'PHPCS Warnings', 'phpcs-errors': 'PHPCS Errors'};
|
||||
titles.push(t[keys[i]]);
|
||||
}
|
||||
|
||||
var data = [titles];
|
||||
|
||||
for (var build in self.data) {
|
||||
var thisBuild = ['#' + build];
|
||||
|
||||
for (var i in keys) {
|
||||
thisBuild.push(parseInt(self.data[build][keys[i]]));
|
||||
}
|
||||
|
||||
data.push(thisBuild);
|
||||
}
|
||||
|
||||
var data = google.visualization.arrayToDataTable(data);
|
||||
var options = {
|
||||
hAxis: {title: 'Build'},
|
||||
vAxis: {title: 'Warnings'},
|
||||
backgroundColor: { fill: 'transparent' }
|
||||
};
|
||||
|
||||
var chart = new google.visualization.LineChart(document.getElementById('build-warnings'));
|
||||
chart.draw(data, options);
|
||||
}
|
||||
});
|
||||
|
||||
PHPCI.registerPlugin(new plugin());
|
64
public/assets/js/class.js
Normal file
64
public/assets/js/class.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Simple JavaScript Inheritance
|
||||
* By John Resig http://ejohn.org/
|
||||
* MIT Licensed.
|
||||
*/
|
||||
// Inspired by base2 and Prototype
|
||||
(function(){
|
||||
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
|
||||
|
||||
// The base Class implementation (does nothing)
|
||||
this.Class = function(){};
|
||||
|
||||
// Create a new Class that inherits from this class
|
||||
Class.extend = function(prop) {
|
||||
var _super = this.prototype;
|
||||
|
||||
// Instantiate a base class (but only create the instance,
|
||||
// don't run the init constructor)
|
||||
initializing = true;
|
||||
var prototype = new this();
|
||||
initializing = false;
|
||||
|
||||
// Copy the properties over onto the new prototype
|
||||
for (var name in prop) {
|
||||
// Check if we're overwriting an existing function
|
||||
prototype[name] = typeof prop[name] == "function" &&
|
||||
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
||||
(function(name, fn){
|
||||
return function() {
|
||||
var tmp = this._super;
|
||||
|
||||
// Add a new ._super() method that is the same method
|
||||
// but on the super-class
|
||||
this._super = _super[name];
|
||||
|
||||
// The method only need to be bound temporarily, so we
|
||||
// remove it when we're done executing
|
||||
var ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
|
||||
return ret;
|
||||
};
|
||||
})(name, prop[name]) :
|
||||
prop[name];
|
||||
}
|
||||
|
||||
// The dummy class constructor
|
||||
function Class() {
|
||||
// All construction is actually done in the init method
|
||||
if ( !initializing && this.init )
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
|
||||
// Populate our constructed prototype object
|
||||
Class.prototype = prototype;
|
||||
|
||||
// Enforce the constructor to be what we expect
|
||||
Class.prototype.constructor = Class;
|
||||
|
||||
// And make this class extendable
|
||||
Class.extend = arguments.callee;
|
||||
|
||||
return Class;
|
||||
};
|
||||
})();
|
6
public/assets/js/jqueryui.js
vendored
Executable file
6
public/assets/js/jqueryui.js
vendored
Executable file
File diff suppressed because one or more lines are too long
|
@ -13,95 +13,6 @@ function confirmDelete(url)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the build screen. Called at regular intervals on /build/view/X
|
||||
*/
|
||||
function updateBuildView(data)
|
||||
{
|
||||
$('#status').attr('class', 'alert');
|
||||
|
||||
var cls;
|
||||
var msg;
|
||||
|
||||
switch(data.status)
|
||||
{
|
||||
case 0:
|
||||
cls = 'alert-info';
|
||||
msg = 'This build has not yet started.';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cls = 'alert-warning';
|
||||
msg = 'This build is in progress.';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cls = 'alert-success';
|
||||
msg = 'This build was successful!';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
cls = 'alert-error';
|
||||
msg = 'This build has failed.';
|
||||
break;
|
||||
}
|
||||
|
||||
$('#status').addClass(cls).text(msg);
|
||||
|
||||
if(data.created)
|
||||
{
|
||||
$('#created').text(data.created);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#created').text('Not created yet.');
|
||||
}
|
||||
|
||||
if(data.started)
|
||||
{
|
||||
$('#started').text(data.started);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#started').text('Not started yet.');
|
||||
}
|
||||
|
||||
if(data.finished)
|
||||
{
|
||||
$('#finished').text(data.finished);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#finished').text('Not finished yet.');
|
||||
}
|
||||
|
||||
if(data.plugins)
|
||||
{
|
||||
$('#plugins').empty();
|
||||
|
||||
for(var plugin in data.plugins)
|
||||
{
|
||||
var row = $('<tr>').addClass(data.plugins[plugin] ? 'success' : 'error');
|
||||
var name = $('<td>').html('<strong>' + formatPluginName(plugin) + '</strong>');
|
||||
var status = $('<td>').text(data.plugins[plugin] ? 'OK' : 'Failed');
|
||||
|
||||
row.append(name);
|
||||
row.append(status);
|
||||
$('#plugins').append(row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var row = $('<tr>');
|
||||
var col = $('<td>').attr('colspan', 2).text('No plugins have run yet.');
|
||||
|
||||
row.append(col);
|
||||
$('#plugins').empty().append(row);
|
||||
}
|
||||
|
||||
$('#log').html(data.log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to initialise the project form:
|
||||
*/
|
||||
|
@ -170,17 +81,129 @@ function setupProjectForm()
|
|||
});
|
||||
}
|
||||
|
||||
var PHPCIObject = Class.extend({
|
||||
buildId: null,
|
||||
plugins: {},
|
||||
observers: {},
|
||||
buildData: {},
|
||||
queries: {},
|
||||
updateInterval: null,
|
||||
|
||||
function formatPluginName (name) {
|
||||
name = name.replace(new RegExp('_', 'g'), ' ');
|
||||
name = ucwords(name);
|
||||
name = name.replace(new RegExp('Php', 'g'), 'PHP');
|
||||
init: function(build) {
|
||||
this.buildId = build;
|
||||
this.registerQuery('build-updated', 10);
|
||||
},
|
||||
|
||||
return name;
|
||||
}
|
||||
registerQuery: function(name, seconds, query) {
|
||||
var self = this;
|
||||
var uri = 'build/meta/' + self.buildId;
|
||||
var query = query || {};
|
||||
|
||||
function ucwords (str) {
|
||||
return (str + '').replace(/^([a-z\u00E0-\u00FC])|\s+([a-z\u00E0-\u00FC])/g, function ($1) {
|
||||
return $1.toUpperCase();
|
||||
if (name == 'build-updated') {
|
||||
uri = 'build/data/' + self.buildId;
|
||||
}
|
||||
|
||||
var cb = function() {
|
||||
$.getJSON(window.PHPCI_URL + uri, query, function(data) {
|
||||
$(window).trigger({type: name, queryData: data});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (seconds != -1) {
|
||||
setInterval(cb, seconds * 1000);
|
||||
}
|
||||
|
||||
return cb;
|
||||
},
|
||||
|
||||
registerPlugin: function(plugin) {
|
||||
this.plugins[plugin.id] = plugin;
|
||||
plugin.register();
|
||||
},
|
||||
|
||||
storePluginOrder: function () {
|
||||
var renderOrder = [];
|
||||
|
||||
$('.ui-plugin > div').each(function() {
|
||||
renderOrder.push($(this).attr('id'));
|
||||
});
|
||||
|
||||
localStorage.setItem('phpci-plugin-order', JSON.stringify(renderOrder));
|
||||
},
|
||||
|
||||
renderPlugins: function() {
|
||||
var self = this;
|
||||
var rendered = [];
|
||||
var renderOrder = localStorage.getItem('phpci-plugin-order');
|
||||
|
||||
if (renderOrder) {
|
||||
renderOrder = JSON.parse(renderOrder);
|
||||
} else {
|
||||
renderOrder = ['build-time', 'build-lines-chart', 'build-warnings-chart', 'build-log'];
|
||||
}
|
||||
|
||||
for (var idx in renderOrder) {
|
||||
var key = renderOrder[idx];
|
||||
self.renderPlugin(self.plugins[key]);
|
||||
rendered.push(key);
|
||||
}
|
||||
|
||||
for (var key in this.plugins) {
|
||||
if (rendered.indexOf(key) == -1) {
|
||||
self.renderPlugin(self.plugins[key]);
|
||||
}
|
||||
}
|
||||
|
||||
$('#plugins').sortable({
|
||||
handle: '.title',
|
||||
connectWith: '#plugins',
|
||||
update: self.storePluginOrder
|
||||
});
|
||||
|
||||
$(window).trigger({type: 'build-updated', queryData: self.buildData});
|
||||
},
|
||||
|
||||
renderPlugin: function(plugin) {
|
||||
var output = $('<div></div>').addClass('box-content').append(plugin.render());
|
||||
var container = $('<div></div>').addClass('ui-plugin ' + plugin.css);
|
||||
var content = $('<div></div>').attr('id', plugin.id).append(output);
|
||||
|
||||
if (plugin.box) {
|
||||
content.addClass('box');
|
||||
}
|
||||
|
||||
if (plugin.title) {
|
||||
content.prepend('<h3 class="title">'+plugin.title+'</h3>');
|
||||
}
|
||||
|
||||
content.append(output);
|
||||
container.append(content);
|
||||
|
||||
$('#plugins').append(container);
|
||||
},
|
||||
|
||||
UiPlugin: Class.extend({
|
||||
id: null,
|
||||
css: 'col-lg-4 col-md-6 col-sm-12 col-xs-12',
|
||||
box: true,
|
||||
|
||||
init: function(){
|
||||
},
|
||||
|
||||
register: function() {
|
||||
var self = this;
|
||||
|
||||
$(window).on('build-updated', function(data) {
|
||||
self.onUpdate(data);
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return '';
|
||||
},
|
||||
|
||||
onUpdate: function (build) {
|
||||
|
||||
}
|
||||
})
|
||||
});
|
Loading…
Reference in a new issue