Add new analytic component "Estimated vs actual time per column"

This commit is contained in:
Patrick Kuijvenhoven
2021-02-22 05:22:45 +01:00
committed by GitHub
parent 6cadf82a63
commit a267aa368b
9 changed files with 151 additions and 1 deletions

View File

@@ -0,0 +1,49 @@
<?php
namespace Kanboard\Analytic;
use Kanboard\Core\Base;
use Kanboard\Model\TaskModel;
/**
* Estimated vs actual time per column
*
* @package analytic
* @author Frederic Guillot
*/
class EstimatedActualColumnAnalytic extends Base
{
/**
* Build report
*
* @access public
* @param integer $project_id Project id
* @return array
*/
public function build($project_id)
{
$rows = $this->db->table(TaskModel::TABLE)
->columns('SUM(time_estimated) AS hours_estimated', 'SUM(time_spent) AS hours_spent', 'column_id')
->eq('project_id', $project_id)
->groupBy('column_id')
->findAll();
$columns = $this->columnModel->getList($project_id);
$metrics = [];
foreach ($columns as $column_id => $column_title) {
$metrics[$column_id] = array(
'hours_spent' => 0,
'hours_estimated' => 0,
'title' => $column_title,
);
}
foreach ($rows as $row) {
$metrics[$row['column_id']]['hours_spent'] = (float) $row['hours_spent'];
$metrics[$row['column_id']]['hours_estimated'] = (float) $row['hours_estimated'];
}
return $metrics;
}
}

View File

@@ -130,6 +130,22 @@ class AnalyticController extends BaseController
$this->commonAggregateMetrics('analytic/burndown', 'score', t('Burndown chart'));
}
/**
* Estimated vs actual time per column
*
* @access public
*/
public function estimatedVsActualByColumn()
{
$project = $this->getProject();
$this->response->html($this->helper->layout->analytic('analytic/estimated_actual_column', array(
'project' => $project,
'metrics' => $this->estimatedActualColumnAnalytic->build($project['id']),
'title' => t('Estimated vs actual time per column'),
)));
}
/**
* Common method for CFD and Burdown chart
*

View File

@@ -15,6 +15,7 @@ use Pimple\Container;
* @property \Kanboard\Analytic\EstimatedTimeComparisonAnalytic $estimatedTimeComparisonAnalytic
* @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
* @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
* @property \Kanboard\Analytic\EstimatedActualColumnAnalytic $estimatedActualColumnAnalytic
* @property \Kanboard\Core\Action\ActionManager $actionManager
* @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
* @property \Kanboard\Core\ExternalTask\ExternalTaskManager $externalTaskManager

View File

@@ -77,6 +77,18 @@ class DateHelper extends Base
return $dtF->diff($dtT)->format($format);
}
/**
* Get duration in hours into human format
*
* @access public
* @param float $hours
* @return string
*/
public function durationHours($hours)
{
return sprintf('%0.2f %s', round($hours, 2), t('hours'));
}
/**
* Get the age of an item in quasi human readable format.
* It's in this format: <1h , NNh, NNd

View File

@@ -24,6 +24,7 @@ class ClassProvider implements ServiceProviderInterface
'EstimatedTimeComparisonAnalytic',
'AverageLeadCycleTimeAnalytic',
'AverageTimeSpentColumnAnalytic',
'EstimatedActualColumnAnalytic',
),
'Model' => array(
'ActionModel',

View File

@@ -0,0 +1,30 @@
<?php if (! $is_ajax): ?>
<div class="page-header">
<h2><?= t('Estimated vs actual time per column') ?></h2>
</div>
<?php endif ?>
<?php if (empty($metrics)): ?>
<p class="alert"><?= t('Not enough data to show the graph.') ?></p>
<?php else: ?>
<?= $this->app->component('chart-project-estimated-actual-column', array(
'metrics' => $metrics,
'labelSpent' => t('Hours Spent'),
'labelEstimated' => t('Hours Estimated'),
)) ?>
<table class="table-striped">
<tr>
<th><?= t('Column') ?></th>
<th><?= t('Hours Spent') ?></th>
<th><?= t('Hours Estimated') ?></th>
</tr>
<?php foreach ($metrics as $column): ?>
<tr>
<td><?= $this->text->e($column['title']) ?></td>
<td><?= $this->dt->durationHours($column['hours_spent']) ?></td>
<td><?= $this->dt->durationHours($column['hours_estimated']) ?></td>
</tr>
<?php endforeach ?>
</table>
<?php endif ?>

View File

@@ -21,6 +21,9 @@
<li <?= $this->app->checkMenuSelection('AnalyticController', 'timeComparison') ?>>
<?= $this->modal->replaceLink(t('Estimated vs actual time'), 'AnalyticController', 'timeComparison', array('project_id' => $project['id'])) ?>
</li>
<li <?= $this->app->checkMenuSelection('AnalyticController', 'estimatedVsActualByColumn') ?>>
<?= $this->modal->replaceLink(t('Estimated vs actual time per column'), 'AnalyticController', 'estimatedVsActualByColumn', array('project_id' => $project['id'])) ?>
</li>
<?= $this->hook->render('template:analytic:sidebar', array('project' => $project)) ?>
</ul>