diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/Controller/Analytic.php | 24 | ||||
| -rw-r--r-- | app/Model/ProjectAnalytic.php | 40 | ||||
| -rw-r--r-- | app/Model/TaskFinder.php | 1 | ||||
| -rw-r--r-- | app/Template/analytic/compare_hours.php | 57 | ||||
| -rw-r--r-- | app/Template/analytic/sidebar.php | 5 | 
5 files changed, 126 insertions, 1 deletions
| diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php index e03d8cab..603ace01 100644 --- a/app/Controller/Analytic.php +++ b/app/Controller/Analytic.php @@ -1,6 +1,7 @@  <?php  namespace Kanboard\Controller; +use Kanboard\Model\Task as TaskModel;  /**   * Project Analytic controller @@ -166,4 +167,27 @@ class Analytic extends Base              'title' => t($title, $project['name']),          )));      } + +    public function compareHours() +    { +        $project = $this->getProject(); +	$params = $this->getProjectFilters('analytic', 'compareHours'); +        $query = $this->taskFilter->search('status:all')->filterByProject($params['project']['id'])->getQuery(); + + +        $paginator = $this->paginator +            ->setUrl('analytics', 'compare_hours') +            ->setMax(30) +            ->setOrder(TaskModel::TABLE.'.id') +            ->setQuery($query) +            ->calculate(); +  +        $stats = $this->projectAnalytic->getHoursByStatus($project['id']); + +        $this->response->html($this->layout('analytic/compare_hours', array( +            'project' => $project, +            'paginator' => $paginator, +            'metrics' => $stats, +        )));  +    }  } diff --git a/app/Model/ProjectAnalytic.php b/app/Model/ProjectAnalytic.php index e77a0368..8a982bd7 100644 --- a/app/Model/ProjectAnalytic.php +++ b/app/Model/ProjectAnalytic.php @@ -179,4 +179,44 @@ class ProjectAnalytic extends Base          return $stats;      } + + +    public function getHoursByStatus($project_id) +    { +        $stats = array(); +        $columns = $this->board->getColumnsList($project_id); + +        // Get the time spent of the last move for each tasks +        $tasks = $this->db +            ->table(Task::TABLE) +            ->columns('id', 'time_estimated', 'time_spent', 'is_active') +            ->eq('project_id', $project_id) +            ->desc('id') +            ->limit(1000) +            ->findAll(); + +        // Init values +        $stats['closed'] = array( +                'time_spent' => 0, +                'time_estimated' => 0, +            ); +	$stats['open'] = array( +                'time_spent' => 0, +                'time_estimated' => 0, +            ); + + +        // Get time spent foreach task/column and take into account the last move +        foreach ($tasks as &$task) { +            if ($task['is_active']) { +                $stats['open']['time_estimated'] += $task['time_estimated']; +                $stats['open']['time_spent'] += $task['time_spent']; +            } else { +                $stats['closed']['time_estimated'] += $task['time_estimated']; +                $stats['closed']['time_spent'] += $task['time_spent']; +            } +        } + +        return $stats; +    }  } diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 9514fe4a..836fbe46 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -122,6 +122,7 @@ class TaskFinder extends Base                  'tasks.recurrence_parent',                  'tasks.recurrence_child',                  'tasks.time_estimated', +                'tasks.time_spent',                  User::TABLE.'.username AS assignee_username',                  User::TABLE.'.name AS assignee_name',                  Category::TABLE.'.name AS category_name', diff --git a/app/Template/analytic/compare_hours.php b/app/Template/analytic/compare_hours.php new file mode 100644 index 00000000..c52023c8 --- /dev/null +++ b/app/Template/analytic/compare_hours.php @@ -0,0 +1,57 @@ +<div class="page-header"> +    <h2><?= t('Compare Estimated Time vs Actual Time') ?></h2> +</div> + +<div class="listing"> +    <ul> +        <li><?= t('Estimated hours: ').'<strong>'.$this->e($metrics['open']['time_estimated']+$metrics['open']['time_estimated']) ?></strong></li> +        <li><?= t('Actual hours: ').'<strong>'.$this->e($metrics['open']['time_spent']+$metrics['closed']['time_spent']) ?></strong></li> +    </ul> +</div> + +<?php if (empty($metrics)): ?> +    <p class="alert"><?= t('Not enough data to show the graph.') ?></p> +<?php else: ?> +<section id="analytic-compare-hours"> +    <div id="chart" data-metrics='<?= json_encode($metrics, JSON_HEX_APOS)?>' data-label-spent="<?= t('Hours Spent') ?>" data-label-estimated="<?= t('Hours Estimated') ?>"></div> + +    <?php if ($paginator->isEmpty()): ?> +        <p class="alert"><?= t('No tasks found.') ?></p> +    <?php elseif (! $paginator->isEmpty()): ?> +        <table class="table-fixed table-small"> +            <tr> +                <th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th> +                <th><?= $paginator->order(t('Title'), 'tasks.title') ?></th> +                <th class="column-5"><?= $paginator->order(t('Status'), 'tasks.is_active') ?></th> +                <th class="column-10"><?= $paginator->order(t('Estimated Time'), 'tasks.time_estimated') ?></th> +                <th class="column-10"><?= $paginator->order(t('Actual Time'), 'tasks.time_spent') ?></th> +            </tr> +            <?php foreach ($paginator->getCollection() as $task): ?> +            <tr> +                <td class="task-table color-<?= $task['color_id'] ?>"> +                    <?= $this->url->link('#'.$this->e($task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> +                </td> +                <td> +                    <?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?> +                </td> +                <td> +                    <?php if ($task['is_active'] == \Kanboard\Model\Task::STATUS_OPEN): ?> +                        <?= t('Open') ?> +                    <?php else: ?> +                        <?= t('Closed') ?> +                    <?php endif ?> +                </td> +                <td> +                    <?= $this->e($task['time_estimated']) ?> +                </td> +                <td> +                    <?= $this->e($task['time_spent']) ?> +                </td> +            </tr> +            <?php endforeach ?> +        </table> + +        <?= $paginator ?> +    <?php endif ?> +</section> +<?php endif ?> diff --git a/app/Template/analytic/sidebar.php b/app/Template/analytic/sidebar.php index c942f7ed..746fcebb 100644 --- a/app/Template/analytic/sidebar.php +++ b/app/Template/analytic/sidebar.php @@ -19,7 +19,10 @@          <li <?= $this->app->getRouterAction() === 'leadandcycletime' ? 'class="active"' : '' ?>>              <?= $this->url->link(t('Lead and cycle time'), 'analytic', 'leadAndCycleTime', array('project_id' => $project['id'])) ?>          </li> +        <li <?= $this->app->getRouterAction() === 'comparehours' ? 'class="active"' : '' ?>> +            <?= $this->url->link(t('Compare hours'), 'analytic', 'compareHours', array('project_id' => $project['id'])) ?> +        </li>      </ul>      <div class="sidebar-collapse"><a href="#" title="<?= t('Hide sidebar') ?>"><i class="fa fa-chevron-left"></i></a></div>      <div class="sidebar-expand" style="display: none"><a href="#" title="<?= t('Expand sidebar') ?>"><i class="fa fa-chevron-right"></i></a></div> -</div>
\ No newline at end of file +</div> | 
