diff options
Diffstat (limited to 'app')
26 files changed, 187 insertions, 3 deletions
diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php index 8b0684d4..e7578da9 100644 --- a/app/Controller/Analytic.php +++ b/app/Controller/Analytic.php @@ -125,4 +125,46 @@ class Analytic extends Base ))); } } + + /** + * Show burndown chart + * + * @access public + */ + public function burndown() + { + $project = $this->getProject(); + $values = $this->request->getValues(); + + $from = $this->request->getStringParam('from', date('Y-m-d', strtotime('-1week'))); + $to = $this->request->getStringParam('to', date('Y-m-d')); + + if (! empty($values)) { + $from = $values['from']; + $to = $values['to']; + } + + if ($this->request->isAjax()) { + $this->response->json(array( + 'metrics' => $this->projectDailySummary->getRawMetricsByDay($project['id'], $from, $to), + 'labels' => array( + 'day' => t('Date'), + 'score' => t('Complexity'), + ) + )); + } + else { + $this->response->html($this->layout('analytic/burndown', array( + 'values' => array( + 'from' => $from, + 'to' => $to, + ), + 'display_graph' => $this->projectDailySummary->countDays($project['id'], $from, $to) >= 2, + 'project' => $project, + 'date_format' => $this->config->get('application_date_format'), + 'date_formats' => $this->dateParser->getAvailableFormats(), + 'title' => t('Burndown chart for "%s"', $project['name']), + ))); + } + } } diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 2e543e48..e9725a00 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 55800071..cd0b4b7f 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index f0a2ef4c..efbf589e 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 48a38f46..e8df52d0 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index a99e19ae..63270415 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -852,4 +852,7 @@ return array( 'uploaded by: %s' => 'Télécharger par : %s', 'uploaded on: %s' => 'Télécharger le : %s', 'size: %s' => 'Taille : %s', + 'Burndown chart for "%s"' => 'Graphique d\'avancement pour « %s »', + 'Burndown chart' => 'Graphique d\'avancement', + 'This chart show the task complexity over the time (Work Remaining).' => 'Ce graphique représente la complexité des tâches en fonction du temps (travail restant).', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index f398629e..ca6e540f 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 385339f0..7c932d02 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 9cedf534..4b56298a 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 31a8006c..374bfe20 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 8dee492e..99de9460 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index f855edb0..e02489a6 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index d67de097..8f2ed825 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index 26a3599a..8245d177 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 90de7470..7b933178 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index f48999cb..72edd63b 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index fb8bc080..fad993d1 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 10d4c604..8c454807 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -850,4 +850,7 @@ return array( // 'uploaded by: %s' => '', // 'uploaded on: %s' => '', // 'size: %s' => '', + // 'Burndown chart for "%s"' => '', + // 'Burndown chart' => '', + // 'This chart show the task complexity over the time (Work Remaining).' => '', ); diff --git a/app/Model/ProjectAnalytic.php b/app/Model/ProjectAnalytic.php index 46f2242d..a663f921 100644 --- a/app/Model/ProjectAnalytic.php +++ b/app/Model/ProjectAnalytic.php @@ -83,6 +83,8 @@ class ProjectAnalytic extends Base $metric['percentage'] = round(($metric['nb_tasks'] * 100) / $total, 2); } + ksort($metrics); + return array_values($metrics); } } diff --git a/app/Model/ProjectDailySummary.php b/app/Model/ProjectDailySummary.php index 0a06bbd4..9e7c836a 100644 --- a/app/Model/ProjectDailySummary.php +++ b/app/Model/ProjectDailySummary.php @@ -20,6 +20,9 @@ class ProjectDailySummary extends Base /** * Update daily totals for the project * + * "total" is the number open of tasks in the column + * "score" is the sum of tasks score in the column + * * @access public * @param integer $project_id Project id * @param string $date Record date (YYYY-MM-DD) @@ -40,6 +43,7 @@ class ProjectDailySummary extends Base 'project_id' => $project_id, 'column_id' => $column_id, 'total' => 0, + 'score' => 0, )); $db->table(ProjectDailySummary::TABLE) @@ -47,6 +51,11 @@ class ProjectDailySummary extends Base ->eq('column_id', $column_id) ->eq('day', $date) ->update(array( + 'score' => $db->table(Task::TABLE) + ->eq('project_id', $project_id) + ->eq('column_id', $column_id) + ->eq('is_active', Task::STATUS_OPEN) + ->sum('score'), 'total' => $db->table(Task::TABLE) ->eq('project_id', $project_id) ->eq('column_id', $column_id) @@ -92,12 +101,39 @@ class ProjectDailySummary extends Base ProjectDailySummary::TABLE.'.column_id', ProjectDailySummary::TABLE.'.day', ProjectDailySummary::TABLE.'.total', + ProjectDailySummary::TABLE.'.score', Board::TABLE.'.title AS column_title' ) ->join(Board::TABLE, 'id', 'column_id') ->eq(ProjectDailySummary::TABLE.'.project_id', $project_id) ->gte('day', $from) ->lte('day', $to) + ->asc(ProjectDailySummary::TABLE.'.day') + ->findAll(); + } + + /** + * Get raw metrics for the project within a data range grouped by day + * + * @access public + * @param integer $project_id Project id + * @param string $from Start date (ISO format YYYY-MM-DD) + * @param string $to End date + * @return array + */ + public function getRawMetricsByDay($project_id, $from, $to) + { + return $this->db->table(ProjectDailySummary::TABLE) + ->columns( + ProjectDailySummary::TABLE.'.day', + 'SUM('.ProjectDailySummary::TABLE.'.total) AS total', + 'SUM('.ProjectDailySummary::TABLE.'.score) AS score' + ) + ->eq(ProjectDailySummary::TABLE.'.project_id', $project_id) + ->gte('day', $from) + ->lte('day', $to) + ->asc(ProjectDailySummary::TABLE.'.day') + ->groupBy(ProjectDailySummary::TABLE.'.day') ->findAll(); } diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index c2bfc97a..6ad6dc51 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,12 @@ use PDO; use Core\Security; use Model\Link; -const VERSION = 63; +const VERSION = 64; + +function version_64($pdo) +{ + $pdo->exec('ALTER TABLE project_daily_summaries ADD COLUMN score INT NOT NULL DEFAULT 0'); +} function version_63($pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 80f29219..b5cf72a6 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,12 @@ use PDO; use Core\Security; use Model\Link; -const VERSION = 44; +const VERSION = 45; + +function version_45($pdo) +{ + $pdo->exec('ALTER TABLE project_daily_summaries ADD COLUMN score INTEGER NOT NULL DEFAULT 0'); +} function version_44($pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index d244cd89..fb1d7d29 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,12 @@ use Core\Security; use PDO; use Model\Link; -const VERSION = 62; +const VERSION = 63; + +function version_63($pdo) +{ + $pdo->exec('ALTER TABLE project_daily_summaries ADD COLUMN score INTEGER NOT NULL DEFAULT 0'); +} function version_62($pdo) { diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php index 6d737734..f865c036 100644 --- a/app/Subscriber/ProjectDailySummarySubscriber.php +++ b/app/Subscriber/ProjectDailySummarySubscriber.php @@ -12,6 +12,7 @@ class ProjectDailySummarySubscriber extends Base implements EventSubscriberInter { return array( Task::EVENT_CREATE => array('execute', 0), + Task::EVENT_UPDATE => array('execute', 0), Task::EVENT_CLOSE => array('execute', 0), Task::EVENT_OPEN => array('execute', 0), Task::EVENT_MOVE_COLUMN => array('execute', 0), diff --git a/app/Template/analytic/burndown.php b/app/Template/analytic/burndown.php new file mode 100644 index 00000000..5ebe1032 --- /dev/null +++ b/app/Template/analytic/burndown.php @@ -0,0 +1,34 @@ +<div class="page-header"> + <h2><?= t('Burndown chart') ?></h2> +</div> + +<?php if (! $display_graph): ?> + <p class="alert"><?= t('Not enough data to show the graph.') ?></p> +<?php else: ?> + <section id="analytic-burndown"> + <div id="chart" data-url="<?= $this->u('analytic', 'burndown', array('project_id' => $project['id'], 'from' => $values['from'], 'to' => $values['to'])) ?>"></div> + </section> +<?php endif ?> + +<hr/> + +<form method="post" class="form-inline" action="<?= $this->u('analytic', 'burndown', array('project_id' => $project['id'])) ?>" autocomplete="off"> + + <?= $this->formCsrf() ?> + + <div class="form-inline-group"> + <?= $this->formLabel(t('Start Date'), 'from') ?> + <?= $this->formText('from', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?> + </div> + + <div class="form-inline-group"> + <?= $this->formLabel(t('End Date'), 'to') ?> + <?= $this->formText('to', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?> + </div> + + <div class="form-inline-group"> + <input type="submit" value="<?= t('Execute') ?>" class="btn btn-blue"/> + </div> +</form> + +<p class="alert alert-info"><?= t('This chart show the task complexity over the time (Work Remaining).') ?></p> diff --git a/app/Template/analytic/sidebar.php b/app/Template/analytic/sidebar.php index a7076db9..f3515281 100644 --- a/app/Template/analytic/sidebar.php +++ b/app/Template/analytic/sidebar.php @@ -10,5 +10,8 @@ <li> <?= $this->a(t('Cumulative flow diagram'), 'analytic', 'cfd', array('project_id' => $project['id'])) ?> </li> + <li> + <?= $this->a(t('Burndown chart'), 'analytic', 'burndown', array('project_id' => $project['id'])) ?> + </li> </ul> </div>
\ No newline at end of file |