From 26fea9b96ba4376a54b5d55b207d3eac040160d7 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 28 Mar 2015 12:39:46 -0400 Subject: Add task transitions csv export --- app/Console/Base.php | 1 + app/Console/TransitionExport.php | 34 +++++++++++ app/Controller/Export.php | 10 ++++ app/Locale/da_DK/translations.php | 3 + app/Locale/de_DE/translations.php | 3 + app/Locale/es_ES/translations.php | 3 + app/Locale/fi_FI/translations.php | 3 + app/Locale/fr_FR/translations.php | 3 + app/Locale/hu_HU/translations.php | 3 + app/Locale/it_IT/translations.php | 3 + app/Locale/ja_JP/translations.php | 3 + app/Locale/nl_NL/translations.php | 3 + app/Locale/pl_PL/translations.php | 3 + app/Locale/pt_BR/translations.php | 3 + app/Locale/ru_RU/translations.php | 3 + app/Locale/sr_Latn_RS/translations.php | 3 + app/Locale/sv_SE/translations.php | 3 + app/Locale/th_TH/translations.php | 3 + app/Locale/tr_TR/translations.php | 3 + app/Locale/zh_CN/translations.php | 3 + app/Model/Transition.php | 103 +++++++++++++++++++++++++++++++++ app/Template/export/transitions.php | 26 +++++++++ app/Template/project/sidebar.php | 3 + docs/cli.markdown | 67 ++++++++++++--------- kanboard | 1 + 25 files changed, 270 insertions(+), 26 deletions(-) create mode 100644 app/Console/TransitionExport.php create mode 100644 app/Template/export/transitions.php diff --git a/app/Console/Base.php b/app/Console/Base.php index aeafbefc..07243080 100644 --- a/app/Console/Base.php +++ b/app/Console/Base.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Command\Command; * @property \Model\Task $task * @property \Model\TaskExport $taskExport * @property \Model\TaskFinder $taskFinder + * @property \Model\Transition $transition */ abstract class Base extends Command { diff --git a/app/Console/TransitionExport.php b/app/Console/TransitionExport.php new file mode 100644 index 00000000..ad988c54 --- /dev/null +++ b/app/Console/TransitionExport.php @@ -0,0 +1,34 @@ +setName('export:transitions') + ->setDescription('Task transitions CSV export') + ->addArgument('project_id', InputArgument::REQUIRED, 'Project id') + ->addArgument('start_date', InputArgument::REQUIRED, 'Start date (YYYY-MM-DD)') + ->addArgument('end_date', InputArgument::REQUIRED, 'End date (YYYY-MM-DD)'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $data = $this->transition->export( + $input->getArgument('project_id'), + $input->getArgument('start_date'), + $input->getArgument('end_date') + ); + + if (is_array($data)) { + Tool::csv($data); + } + } +} diff --git a/app/Controller/Export.php b/app/Controller/Export.php index 1997a4ea..b8f932c1 100644 --- a/app/Controller/Export.php +++ b/app/Controller/Export.php @@ -72,4 +72,14 @@ class Export extends Base { $this->common('projectDailySummary', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export')); } + + /** + * Transition export + * + * @access public + */ + public function transitions() + { + $this->common('transition', 'export', t('Transitions'), 'transitions', t('Task transitions export')); + } } diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 8263cbb9..17b8362d 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 6202cd1b..e3eeea52 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index edd49a33..ac76ff74 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 9a62bf54..abf53362 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 6baca123..15705106 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -814,4 +814,7 @@ return array( 'Transitions' => 'Transitions', 'Executer' => 'Exécutant', 'Time spent in the column' => 'Temps passé dans la colonne', + 'Task transitions' => 'Transitions des tâches', + 'Task transitions export' => 'Export des transitions des tâches', + 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => 'Ce rapport contient tous les mouvements de colonne pour chaque tâche avec la date, l\'utilisateur et le temps passé pour chaque transition.', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index 42252f2b..ecf7b6e3 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 33072967..511f1d44 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index cbc40254..014ca0f4 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index bf6c3665..199c33b8 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index da4bd8ac..3d9fcb25 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index dae703ea..9d0de537 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index bd26ea53..e6e3cff4 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index bfd9352d..ec30a3b2 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 31c5bf91..5f460a25 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 228b5e3c..b017a255 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 9d7cfdd2..fc89f1c5 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 8859cd17..03cfafe4 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -812,4 +812,7 @@ return array( // 'Transitions' => '', // 'Executer' => '', // 'Time spent in the column' => '', + // 'Task transitions' => '', + // 'Task transitions export' => '', + // 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '', ); diff --git a/app/Model/Transition.php b/app/Model/Transition.php index 583d3aca..cb759e4a 100644 --- a/app/Model/Transition.php +++ b/app/Model/Transition.php @@ -64,4 +64,107 @@ class Transition extends Base ->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') ->findAll(); } + + /** + * Get all transitions by project + * + * @access public + * @param integer $project_id + * @param mixed $from Start date (timestamp or user formatted date) + * @param mixed $to End date (timestamp or user formatted date) + * @return array + */ + public function getAllByProjectAndDate($project_id, $from, $to) + { + if (! is_numeric($from)) { + $from = $this->dateParser->removeTimeFromTimestamp($this->dateParser->getTimestamp($from)); + } + + if (! is_numeric($to)) { + $to = $this->dateParser->removeTimeFromTimestamp(strtotime('+1 day', $this->dateParser->getTimestamp($to))); + } + + return $this->db->table(self::TABLE) + ->columns( + Task::TABLE.'.id', + Task::TABLE.'.title', + 'src.title as src_column', + 'dst.title as dst_column', + User::TABLE.'.name', + User::TABLE.'.username', + self::TABLE.'.user_id', + self::TABLE.'.date', + self::TABLE.'.time_spent' + ) + ->gte('date', $from) + ->lte('date', $to) + ->eq(self::TABLE.'.project_id', $project_id) + ->desc('date') + ->join(Task::TABLE, 'id', 'task_id') + ->join(User::TABLE, 'id', 'user_id') + ->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src') + ->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') + ->findAll(); + } + + /** + * Get project export + * + * @access public + * @param integer $project_id Project id + * @param mixed $from Start date (timestamp or user formatted date) + * @param mixed $to End date (timestamp or user formatted date) + * @return array + */ + public function export($project_id, $from, $to) + { + $results = array($this->getColumns()); + $transitions = $this->getAllByProjectAndDate($project_id, $from, $to); + + foreach ($transitions as $transition) { + $results[] = $this->format($transition); + } + + return $results; + } + + /** + * Get column titles + * + * @access public + * @return string[] + */ + public function getColumns() + { + return array( + e('Id'), + e('Task Title'), + e('Source column'), + e('Destination column'), + e('Executer'), + e('Date'), + e('Time spent'), + ); + } + + /** + * Format the output of a transition array + * + * @access public + * @param array $transition + * @return array + */ + public function format(array $transition) + { + $values = array(); + $values[] = $transition['id']; + $values[] = $transition['title']; + $values[] = $transition['src_column']; + $values[] = $transition['dst_column']; + $values[] = $transition['name'] ?: $transition['username']; + $values[] = date('Y-m-d H:i', $transition['date']); + $values[] = round($transition['time_spent'] / 3600, 2); + + return $values; + } } diff --git a/app/Template/export/transitions.php b/app/Template/export/transitions.php new file mode 100644 index 00000000..7cd190e0 --- /dev/null +++ b/app/Template/export/transitions.php @@ -0,0 +1,26 @@ + + +

+ +
+ + formHidden('controller', $values) ?> + formHidden('action', $values) ?> + formHidden('project_id', $values) ?> + + formLabel(t('Start Date'), 'from') ?> + formText('from', $values, $errors, array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
+ + formLabel(t('End Date'), 'to') ?> + formText('to', $values, $errors, array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?> + +
+ +
+ +
+
\ No newline at end of file diff --git a/app/Template/project/sidebar.php b/app/Template/project/sidebar.php index 4afc8ba9..47458144 100644 --- a/app/Template/project/sidebar.php +++ b/app/Template/project/sidebar.php @@ -62,6 +62,9 @@
  • a(t('Subtasks'), 'export', 'subtasks', array('project_id' => $project['id'])) ?>
  • +
  • + a(t('Task transitions'), 'export', 'transitions', array('project_id' => $project['id'])) ?> +
  • a(t('Daily project summary'), 'export', 'summary', array('project_id' => $project['id'])) ?>
  • diff --git a/docs/cli.markdown b/docs/cli.markdown index 0e2a0203..b742e0ac 100644 --- a/docs/cli.markdown +++ b/docs/cli.markdown @@ -17,16 +17,16 @@ $ ./kanboard Kanboard version master Usage: - [options] command [arguments] + command [options] [arguments] Options: - --help (-h) Display this help message. - --quiet (-q) Do not output any message. - --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug. - --version (-V) Display this application version. - --ansi Force ANSI output. - --no-ansi Disable ANSI output. - --no-interaction (-n) Do not ask any interactive question. + --help (-h) Display this help message + --quiet (-q) Do not output any message + --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + --version (-V) Display this application version + --ansi Force ANSI output + --no-ansi Disable ANSI output + --no-interaction (-n) Do not ask any interactive question Available commands: help Displays help for a command @@ -35,6 +35,7 @@ export export:daily-project-summary Daily project summary CSV export (number of tasks per column and per day) export:subtasks Subtasks CSV export export:tasks Tasks CSV export + export:transitions Task transitions CSV export notification notification:overdue-tasks Send notifications for overdue tasks projects @@ -44,6 +45,22 @@ projects Available commands ------------------ +### Tasks CSV export + +Usage: + +```bash +./kanboard export:tasks +``` + +Example: + +```bash +./kanboard export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +``` + +CSV data are sent to `stdout`. + ### Subtasks CSV export Usage: @@ -58,21 +75,33 @@ Example: ./kanboard export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` -### Tasks CSV export +### Task transitions CSV export Usage: ```bash -./kanboard export:tasks +./kanboard export:transitions ``` Example: ```bash -./kanboard export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./kanboard export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` -CSV data are sent to stdout. +### Export daily summaries data in CSV + +The exported data will be printed on the standard output: + +```bash +./kanboard export:daily-project-summary +``` + +Example: + +```bash +./kanboard export:daily-project-summary 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +``` ### Send notifications for overdue tasks @@ -111,17 +140,3 @@ Run calculation for Project #0 Run calculation for Project #1 Run calculation for Project #10 ``` - -### Export daily summaries data in CSV - -The exported data will be printed on the standard output: - -```bash -./kanboard export:daily-project-summary -``` - -Example: - -```bash -./kanboard export:daily-project-summary 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv -``` diff --git a/kanboard b/kanboard index 8b772f84..f6456ea1 100755 --- a/kanboard +++ b/kanboard @@ -14,4 +14,5 @@ $application->add(new Console\SubtaskExport($container)); $application->add(new Console\TaskExport($container)); $application->add(new Console\ProjectDailySummaryCalculation($container)); $application->add(new Console\ProjectDailySummaryExport($container)); +$application->add(new Console\TransitionExport($container)); $application->run(); -- cgit v1.2.3