From 1487cb27634161ef558c367150213bc7077e4198 Mon Sep 17 00:00:00 2001 From: Frédéric Guillot Date: Thu, 13 Nov 2014 20:37:37 -0500 Subject: Add graph for user repartition --- app/Controller/Analytic.php | 34 ++++++++++++++++++++-- app/Locale/da_DK/translations.php | 2 ++ app/Locale/de_DE/translations.php | 2 ++ app/Locale/es_ES/translations.php | 2 ++ app/Locale/fi_FI/translations.php | 2 ++ app/Locale/fr_FR/translations.php | 2 ++ app/Locale/it_IT/translations.php | 2 ++ app/Locale/ja_JP/translations.php | 2 ++ app/Locale/pl_PL/translations.php | 2 ++ app/Locale/pt_BR/translations.php | 2 ++ app/Locale/ru_RU/translations.php | 2 ++ app/Locale/sv_SE/translations.php | 2 ++ app/Locale/th_TH/translations.php | 2 ++ app/Locale/zh_CN/translations.php | 2 ++ app/Model/Acl.php | 2 +- app/Model/ProjectAnalytic.php | 39 ++++++++++++++++++++++++- app/Template/analytic/repartition.php | 29 ------------------- app/Template/analytic/sidebar.php | 5 +++- app/Template/analytic/tasks.php | 29 +++++++++++++++++++ app/Template/analytic/users.php | 29 +++++++++++++++++++ app/Template/board/filters.php | 2 +- assets/js/analytic.js | 54 +++++++++++++++++++++++++++++++++-- assets/js/app.js | 54 +++++++++++++++++++++++++++++++++-- 23 files changed, 261 insertions(+), 42 deletions(-) delete mode 100644 app/Template/analytic/repartition.php create mode 100644 app/Template/analytic/tasks.php create mode 100644 app/Template/analytic/users.php diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php index 68177c83..7d112e6a 100644 --- a/app/Controller/Analytic.php +++ b/app/Controller/Analytic.php @@ -27,11 +27,11 @@ class Analytic extends Base } /** - * Show task distribution graph + * Show tasks distribution graph * * @access public */ - public function repartition() + public function tasks() { $project = $this->getProject(); $metrics = $this->projectAnalytic->getTaskRepartition($project['id']); @@ -46,11 +46,39 @@ class Analytic extends Base )); } else { - $this->response->html($this->layout('analytic/repartition', array( + $this->response->html($this->layout('analytic/tasks', array( 'project' => $project, 'metrics' => $metrics, 'title' => t('Task repartition for "%s"', $project['name']), ))); } } + + /** + * Show users repartition + * + * @access public + */ + public function users() + { + $project = $this->getProject(); + $metrics = $this->projectAnalytic->getUserRepartition($project['id']); + + if ($this->request->isAjax()) { + $this->response->json(array( + 'metrics' => $metrics, + 'labels' => array( + 'user' => t('User'), + 'nb_tasks' => t('Number of tasks'), + ) + )); + } + else { + $this->response->html($this->layout('analytic/users', array( + 'project' => $project, + 'metrics' => $metrics, + 'title' => t('User repartition for "%s"', $project['name']), + ))); + } + } } diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 2cb77240..6e355f51 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index fb03b616..1a8109c1 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index c54267ff..e0b47923 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 59cea9f7..200b74e7 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index d36b0e93..e4edb433 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -573,4 +573,6 @@ return array( 'Analytics' => 'Analytique', 'Subtask' => 'Sous-tâche', 'My subtasks' => 'Mes sous-tâches', + 'User repartition' => 'Répartition des utilisateurs', + 'User repartition for "%s"' => 'Répartition des utilisateurs pour « %s »', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index e4f9fc8b..7ef579a7 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 0e75fc23..c1625c48 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index f0277429..0c7b4834 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index fd1fc1cf..e0969b6d 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 9c486ff4..27f9644e 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index a56c7db5..f5f4f080 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index f2e51d12..7099891f 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 4b86a7e1..2490709b 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -573,4 +573,6 @@ return array( // 'Analytics' => '', // 'Subtask' => '', // 'My subtasks' => '', + // 'User repartition' => '', + // 'User repartition for "%s"' => '', ); diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 52957130..25e98850 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -41,7 +41,7 @@ class Acl extends Base 'task' => array('show', 'create', 'save', 'edit', 'update', 'close', 'open', 'duplicate', 'remove', 'description', 'move', 'copy', 'time'), 'category' => array('index', 'save', 'edit', 'update', 'confirm', 'remove'), 'action' => array('index', 'event', 'params', 'create', 'confirm', 'remove'), - 'analytic' => array('repartition'), + 'analytic' => array('tasks', 'users'), ); /** diff --git a/app/Model/ProjectAnalytic.php b/app/Model/ProjectAnalytic.php index ccd2c4c9..8ecbf1f0 100644 --- a/app/Model/ProjectAnalytic.php +++ b/app/Model/ProjectAnalytic.php @@ -11,7 +11,7 @@ namespace Model; class ProjectAnalytic extends Base { /** - * Get task repartition + * Get tasks repartition * * @access public * @param integer $project_id Project id @@ -40,4 +40,41 @@ class ProjectAnalytic extends Base return $metrics; } + + /** + * Get users repartition + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function getUserRepartition($project_id) + { + $metrics = array(); + $total = 0; + $tasks = $this->taskFinder->getAll($project_id); + $users = $this->projectPermission->getMemberList($project_id); + + foreach ($tasks as $task) { + + $user = $users[$task['owner_id']]; + $total++; + + if (! isset($metrics[$user])) { + $metrics[$user] = array( + 'nb_tasks' => 0, + 'percentage' => 0, + 'user' => $user, + ); + } + + $metrics[$user]['nb_tasks']++; + } + + foreach ($metrics as &$metric) { + $metric['percentage'] = round(($metric['nb_tasks'] * 100) / $total, 2); + } + + return array_values($metrics); + } } diff --git a/app/Template/analytic/repartition.php b/app/Template/analytic/repartition.php deleted file mode 100644 index f20b6a0c..00000000 --- a/app/Template/analytic/repartition.php +++ /dev/null @@ -1,29 +0,0 @@ - -
- -
- - - - - - - - - - - - - - -
- - - - - % -
- -
diff --git a/app/Template/analytic/sidebar.php b/app/Template/analytic/sidebar.php index df6835ee..dded245a 100644 --- a/app/Template/analytic/sidebar.php +++ b/app/Template/analytic/sidebar.php @@ -2,7 +2,10 @@

\ No newline at end of file diff --git a/app/Template/analytic/tasks.php b/app/Template/analytic/tasks.php new file mode 100644 index 00000000..7ae9c254 --- /dev/null +++ b/app/Template/analytic/tasks.php @@ -0,0 +1,29 @@ + +
+ +
+ + + + + + + + + + + + + + +
+ + + + + % +
+ +
diff --git a/app/Template/analytic/users.php b/app/Template/analytic/users.php new file mode 100644 index 00000000..89f00686 --- /dev/null +++ b/app/Template/analytic/users.php @@ -0,0 +1,29 @@ + +
+ +
+ + + + + + + + + + + + + + +
+ + + + + % +
+ +
diff --git a/app/Template/board/filters.php b/app/Template/board/filters.php index 21e51d98..76cbca2d 100644 --- a/app/Template/board/filters.php +++ b/app/Template/board/filters.php @@ -25,7 +25,7 @@
  • - $project['id'])) ?> + $project['id'])) ?>
  • diff --git a/assets/js/analytic.js b/assets/js/analytic.js index 32d3037a..22fb672e 100644 --- a/assets/js/analytic.js +++ b/assets/js/analytic.js @@ -4,15 +4,18 @@ Kanboard.Analytic = (function() { return { Init: function() { - if (Kanboard.Exists("analytic-repartition")) { - Kanboard.Analytic.Repartition.Init(); + if (Kanboard.Exists("analytic-task-repartition")) { + Kanboard.Analytic.TaskRepartition.Init(); + } + else if (Kanboard.Exists("analytic-user-repartition")) { + Kanboard.Analytic.UserRepartition.Init(); } } }; })(); -Kanboard.Analytic.Repartition = (function() { +Kanboard.Analytic.TaskRepartition = (function() { function fetchData() { @@ -56,3 +59,48 @@ Kanboard.Analytic.Repartition = (function() { }; })(); + +Kanboard.Analytic.UserRepartition = (function() { + + function fetchData() + { + jQuery.getJSON($("#chart").attr("data-url"), function(data) { + drawGraph(data.metrics, data.labels); + }); + } + + function drawGraph(metrics, labels) + { + var series = prepareSeries(metrics, labels); + + var svg = dimple.newSvg("#chart", 700, 350); + + var chart = new dimple.chart(svg, series); + chart.addMeasureAxis("p", labels["nb_tasks"]); + var ring = chart.addSeries(labels["user"], dimple.plot.pie); + ring.innerRadius = "50%"; + chart.addLegend(0, 0, 100, 100, "left"); + chart.draw(); + } + + function prepareSeries(metrics, labels) + { + var series = []; + + for (var i = 0; i < metrics.length; i++) { + + var serie = {}; + serie[labels["nb_tasks"]] = metrics[i]["nb_tasks"]; + serie[labels["user"]] = metrics[i]["user"]; + + series.push(serie); + } + + return series; + } + + return { + Init: fetchData + }; + +})(); diff --git a/assets/js/app.js b/assets/js/app.js index 55bc4039..ed017b0b 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -273,15 +273,18 @@ Kanboard.Analytic = (function() { return { Init: function() { - if (Kanboard.Exists("analytic-repartition")) { - Kanboard.Analytic.Repartition.Init(); + if (Kanboard.Exists("analytic-task-repartition")) { + Kanboard.Analytic.TaskRepartition.Init(); + } + else if (Kanboard.Exists("analytic-user-repartition")) { + Kanboard.Analytic.UserRepartition.Init(); } } }; })(); -Kanboard.Analytic.Repartition = (function() { +Kanboard.Analytic.TaskRepartition = (function() { function fetchData() { @@ -324,6 +327,51 @@ Kanboard.Analytic.Repartition = (function() { Init: fetchData }; +})(); + +Kanboard.Analytic.UserRepartition = (function() { + + function fetchData() + { + jQuery.getJSON($("#chart").attr("data-url"), function(data) { + drawGraph(data.metrics, data.labels); + }); + } + + function drawGraph(metrics, labels) + { + var series = prepareSeries(metrics, labels); + + var svg = dimple.newSvg("#chart", 700, 350); + + var chart = new dimple.chart(svg, series); + chart.addMeasureAxis("p", labels["nb_tasks"]); + var ring = chart.addSeries(labels["user"], dimple.plot.pie); + ring.innerRadius = "50%"; + chart.addLegend(0, 0, 100, 100, "left"); + chart.draw(); + } + + function prepareSeries(metrics, labels) + { + var series = []; + + for (var i = 0; i < metrics.length; i++) { + + var serie = {}; + serie[labels["nb_tasks"]] = metrics[i]["nb_tasks"]; + serie[labels["user"]] = metrics[i]["user"]; + + series.push(serie); + } + + return series; + } + + return { + Init: fetchData + }; + })(); // Initialization $(function() { -- cgit v1.2.3