summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Console/SubtaskExport.php34
-rw-r--r--app/Controller/Export.php75
-rw-r--r--app/Controller/Project.php66
-rw-r--r--app/Locale/da_DK/translations.php7
-rw-r--r--app/Locale/de_DE/translations.php7
-rw-r--r--app/Locale/es_ES/translations.php7
-rw-r--r--app/Locale/fi_FI/translations.php7
-rw-r--r--app/Locale/fr_FR/translations.php7
-rw-r--r--app/Locale/hu_HU/translations.php7
-rw-r--r--app/Locale/it_IT/translations.php7
-rw-r--r--app/Locale/ja_JP/translations.php7
-rw-r--r--app/Locale/pl_PL/translations.php7
-rw-r--r--app/Locale/pt_BR/translations.php7
-rw-r--r--app/Locale/ru_RU/translations.php7
-rw-r--r--app/Locale/sv_SE/translations.php7
-rw-r--r--app/Locale/th_TH/translations.php7
-rw-r--r--app/Locale/zh_CN/translations.php7
-rw-r--r--app/Model/Acl.php14
-rw-r--r--app/Model/SubTask.php6
-rw-r--r--app/Model/SubtaskExport.php119
-rw-r--r--app/ServiceProvider/ClassProvider.php1
-rw-r--r--app/Template/export/subtasks.php24
-rw-r--r--app/Template/export/summary.php (renamed from app/Template/project/export_daily_summary.php)0
-rw-r--r--app/Template/export/tasks.php (renamed from app/Template/project/export_tasks.php)0
-rw-r--r--app/Template/project/sidebar.php7
-rw-r--r--docs/cli.markdown15
-rwxr-xr-xkanboard1
27 files changed, 380 insertions, 80 deletions
diff --git a/app/Console/SubtaskExport.php b/app/Console/SubtaskExport.php
new file mode 100644
index 00000000..167a9225
--- /dev/null
+++ b/app/Console/SubtaskExport.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Console;
+
+use Core\Tool;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class SubtaskExport extends Base
+{
+ protected function configure()
+ {
+ $this
+ ->setName('export:subtasks')
+ ->setDescription('Subtasks 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->subtaskExport->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
new file mode 100644
index 00000000..1997a4ea
--- /dev/null
+++ b/app/Controller/Export.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Controller;
+
+/**
+ * Export controller
+ *
+ * @package controller
+ * @author Frederic Guillot
+ */
+class Export extends Base
+{
+ /**
+ * Common export method
+ *
+ * @access private
+ */
+ private function common($model, $method, $filename, $action, $page_title)
+ {
+ $project = $this->getProject();
+ $from = $this->request->getStringParam('from');
+ $to = $this->request->getStringParam('to');
+
+ if ($from && $to) {
+ $data = $this->$model->$method($project['id'], $from, $to);
+ $this->response->forceDownload($filename.'.csv');
+ $this->response->csv($data);
+ }
+
+ $this->response->html($this->projectLayout('export/'.$action, array(
+ 'values' => array(
+ 'controller' => 'export',
+ 'action' => $action,
+ 'project_id' => $project['id'],
+ 'from' => $from,
+ 'to' => $to,
+ ),
+ 'errors' => array(),
+ 'date_format' => $this->config->get('application_date_format'),
+ 'date_formats' => $this->dateParser->getAvailableFormats(),
+ 'project' => $project,
+ 'title' => $page_title,
+ )));
+ }
+
+ /**
+ * Task export
+ *
+ * @access public
+ */
+ public function tasks()
+ {
+ $this->common('taskExport', 'export', t('Tasks'), 'tasks', t('Tasks Export'));
+ }
+
+ /**
+ * Subtask export
+ *
+ * @access public
+ */
+ public function subtasks()
+ {
+ $this->common('subtaskExport', 'export', t('Subtasks'), 'subtasks', t('Subtasks Export'));
+ }
+
+ /**
+ * Daily project summary export
+ *
+ * @access public
+ */
+ public function summary()
+ {
+ $this->common('projectDailySummary', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
+ }
+}
diff --git a/app/Controller/Project.php b/app/Controller/Project.php
index 95779154..d0da53d0 100644
--- a/app/Controller/Project.php
+++ b/app/Controller/Project.php
@@ -57,72 +57,6 @@ class Project extends Base
}
/**
- * Task export
- *
- * @access public
- */
- public function exportTasks()
- {
- $project = $this->getProject();
- $from = $this->request->getStringParam('from');
- $to = $this->request->getStringParam('to');
-
- if ($from && $to) {
- $data = $this->taskExport->export($project['id'], $from, $to);
- $this->response->forceDownload('Tasks_'.date('Y_m_d_H_i').'.csv');
- $this->response->csv($data);
- }
-
- $this->response->html($this->projectLayout('project/export_tasks', array(
- 'values' => array(
- 'controller' => 'project',
- 'action' => 'exportTasks',
- 'project_id' => $project['id'],
- 'from' => $from,
- 'to' => $to,
- ),
- 'errors' => array(),
- 'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
- 'project' => $project,
- 'title' => t('Tasks Export')
- )));
- }
-
- /**
- * Daily project summary export
- *
- * @access public
- */
- public function exportDailyProjectSummary()
- {
- $project = $this->getProject();
- $from = $this->request->getStringParam('from');
- $to = $this->request->getStringParam('to');
-
- if ($from && $to) {
- $data = $this->projectDailySummary->getAggregatedMetrics($project['id'], $from, $to);
- $this->response->forceDownload('Daily_Summary_'.date('Y_m_d_H_i').'.csv');
- $this->response->csv($data);
- }
-
- $this->response->html($this->projectLayout('project/export_daily_summary', array(
- 'values' => array(
- 'controller' => 'project',
- 'action' => 'exportDailyProjectSummary',
- 'project_id' => $project['id'],
- 'from' => $from,
- 'to' => $to,
- ),
- 'errors' => array(),
- 'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
- 'project' => $project,
- 'title' => t('Daily project summary export')
- )));
- }
-
- /**
* Public access management
*
* @access public
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index c16e3d92..8b529d10 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index d0f9ee40..58d99e8d 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index 1dcb0768..ab6518a5 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index ff5a365d..0ba5acd2 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index b830a435..298813da 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -637,4 +637,11 @@ return array(
'Project manager' => 'Chef de projet',
'Project member' => 'Membre du projet',
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Un chef de projet peut changer les paramètres du projet et possède plus de privilèges qu\'un utilisateur standard.',
+ 'Gitlab Issue' => 'Ticket Gitlab',
+ 'Subtask Id' => 'Identifiant de la sous-tâche',
+ 'Subtasks' => 'Sous-tâches',
+ 'Subtasks Export' => 'Exportation des sous-tâches',
+ 'Subtasks exportation for "%s"' => 'Exportation des sous-tâches pour le projet « %s »',
+ 'Task Title' => 'Titre de la tâche',
+ 'Untitled' => 'Sans nom',
);
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index b7e5ae25..12123634 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index 828c72a7..5d4f35a1 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index e424a151..dfa9a365 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index aa4e7428..058ff567 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index cb873cd2..f585bce8 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index e3ad20df..03eda536 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 779cce06..12b4b2e2 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index c0cd5292..4d2940de 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index a7810989..15db3d68 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -637,4 +637,11 @@ return array(
// 'Project manager' => '',
// 'Project member' => '',
// 'A project manager can change the settings of the project and have more privileges than a standard user.' => '',
+ // 'Gitlab Issue' => '',
+ // 'Subtask Id' => '',
+ // 'Subtasks' => '',
+ // 'Subtasks Export' => '',
+ // 'Subtasks exportation for "%s"' => '',
+ // 'Task Title' => '',
+ // 'Untitled' => '',
);
diff --git a/app/Model/Acl.php b/app/Model/Acl.php
index 9c3f5e06..599ff055 100644
--- a/app/Model/Acl.php
+++ b/app/Model/Acl.php
@@ -50,7 +50,8 @@ class Acl extends Base
'analytic' => '*',
'board' => array('movecolumn', 'edit', 'update', 'add', 'remove'),
'category' => '*',
- 'project' => array('edit', 'update', 'exporttasks', 'exportdailyprojectsummary', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
+ 'export' => array('tasks', 'subtasks', 'summary'),
+ 'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
'swimlane' => '*',
);
@@ -179,7 +180,7 @@ class Acl extends Base
// Check project member permissions
if ($this->isMemberAction($controller, $action)) {
- return $this->isMemberActionAllowed($project_id);
+ return $project_id > 0 && $this->projectPermission->isMember($project_id, $this->userSession->getId());
}
// Other applications actions are allowed
@@ -188,11 +189,10 @@ class Acl extends Base
public function isManagerActionAllowed($project_id)
{
- return $project_id > 0 && $this->projectPermission->isManager($project_id, $this->userSession->getId());
- }
+ if ($this->userSession->isAdmin()) {
+ return true;
+ }
- public function isMemberActionAllowed($project_id)
- {
- return $project_id > 0 && $this->projectPermission->isMember($project_id, $this->userSession->getId());
+ return $project_id > 0 && $this->projectPermission->isManager($project_id, $this->userSession->getId());
}
}
diff --git a/app/Model/SubTask.php b/app/Model/SubTask.php
index adc5aa73..1c5d1bf0 100644
--- a/app/Model/SubTask.php
+++ b/app/Model/SubTask.php
@@ -58,15 +58,11 @@ class SubTask extends Base
*/
public function getStatusList()
{
- $status = array(
+ return array(
self::STATUS_TODO => t('Todo'),
self::STATUS_INPROGRESS => t('In progress'),
self::STATUS_DONE => t('Done'),
);
-
- asort($status);
-
- return $status;
}
/**
diff --git a/app/Model/SubtaskExport.php b/app/Model/SubtaskExport.php
new file mode 100644
index 00000000..50b028e2
--- /dev/null
+++ b/app/Model/SubtaskExport.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace Model;
+
+/**
+ * Subtask Export
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class SubtaskExport extends Base
+{
+ /**
+ * Subtask statuses
+ *
+ * @access private
+ * @var array
+ */
+ private $subtask_status = array();
+
+ /**
+ * Fetch subtasks and return the prepared CSV
+ *
+ * @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)
+ {
+ $this->subtask_status = $this->subTask->getStatusList();
+ $subtasks = $this->getSubtasks($project_id, $from, $to);
+ $results = array($this->getColumns());
+
+ foreach ($subtasks as $subtask) {
+ $results[] = $this->format($subtask);
+ }
+
+ return $results;
+ }
+
+ /**
+ * Get column titles
+ *
+ * @access public
+ * @return string[]
+ */
+ public function getColumns()
+ {
+ return array(
+ e('Subtask Id'),
+ e('Title'),
+ e('Status'),
+ e('Assignee'),
+ e('Time estimated'),
+ e('Time spent'),
+ e('Task Id'),
+ e('Task Title'),
+ );
+ }
+
+ /**
+ * Format the output of a subtask array
+ *
+ * @access public
+ * @param array $subtask Subtask properties
+ * @return array
+ */
+ public function format(array $subtask)
+ {
+ $values = array();
+ $values[] = $subtask['id'];
+ $values[] = $subtask['title'];
+ $values[] = $this->subtask_status[$subtask['status']];
+ $values[] = $subtask['assignee_name'] ?: $subtask['assignee_username'];
+ $values[] = $subtask['time_estimated'];
+ $values[] = $subtask['time_spent'];
+ $values[] = $subtask['task_id'];
+ $values[] = $subtask['task_title'];
+
+ return $values;
+ }
+
+ /**
+ * Get all subtasks for a given project
+ *
+ * @access public
+ * @param integer $task_id Task 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 getSubtasks($project_id, $from, $to)
+ {
+ if (! is_numeric($from)) {
+ $from = $this->dateParser->resetDateToMidnight($this->dateParser->getTimestamp($from));
+ }
+
+ if (! is_numeric($to)) {
+ $to = $this->dateParser->resetDateToMidnight(strtotime('+1 day', $this->dateParser->getTimestamp($to)));
+ }
+
+ return $this->db->table(SubTask::TABLE)
+ ->eq('project_id', $project_id)
+ ->columns(
+ SubTask::TABLE.'.*',
+ User::TABLE.'.username AS assignee_username',
+ User::TABLE.'.name AS assignee_name',
+ Task::TABLE.'.title AS task_title'
+ )
+ ->gte('date_creation', $from)
+ ->lte('date_creation', $to)
+ ->join(Task::TABLE, 'id', 'task_id')
+ ->join(User::TABLE, 'id', 'user_id')
+ ->asc(SubTask::TABLE.'.id')
+ ->findAll();
+ }
+}
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index f8d20262..3177276a 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -32,6 +32,7 @@ class ClassProvider implements ServiceProviderInterface
'ProjectPermission',
'SubTask',
'SubtaskPaginator',
+ 'SubtaskExport',
'Swimlane',
'Task',
'TaskCreation',
diff --git a/app/Template/export/subtasks.php b/app/Template/export/subtasks.php
new file mode 100644
index 00000000..aa999a56
--- /dev/null
+++ b/app/Template/export/subtasks.php
@@ -0,0 +1,24 @@
+<div class="page-header">
+ <h2>
+ <?= t('Subtasks exportation for "%s"', $project['name']) ?>
+ </h2>
+</div>
+
+<form method="get" action="?" autocomplete="off">
+
+ <?= $this->formHidden('controller', $values) ?>
+ <?= $this->formHidden('action', $values) ?>
+ <?= $this->formHidden('project_id', $values) ?>
+
+ <?= $this->formLabel(t('Start Date'), 'from') ?>
+ <?= $this->formText('from', $values, $errors, array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?><br/>
+
+ <?= $this->formLabel(t('End Date'), 'to') ?>
+ <?= $this->formText('to', $values, $errors, array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
+
+ <div class="form-help"><?= t('Others formats accepted: %s and %s', date('Y-m-d'), date('Y_m_d')) ?></div>
+
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Execute') ?>" class="btn btn-blue"/>
+ </div>
+</form> \ No newline at end of file
diff --git a/app/Template/project/export_daily_summary.php b/app/Template/export/summary.php
index 191d36b6..191d36b6 100644
--- a/app/Template/project/export_daily_summary.php
+++ b/app/Template/export/summary.php
diff --git a/app/Template/project/export_tasks.php b/app/Template/export/tasks.php
index e502085c..e502085c 100644
--- a/app/Template/project/export_tasks.php
+++ b/app/Template/export/tasks.php
diff --git a/app/Template/project/sidebar.php b/app/Template/project/sidebar.php
index f28f6b0d..f4809fde 100644
--- a/app/Template/project/sidebar.php
+++ b/app/Template/project/sidebar.php
@@ -54,10 +54,13 @@
<h2><?= t('Exports') ?></h2>
<ul>
<li>
- <?= $this->a(t('Tasks'), 'project', 'exportTasks', array('project_id' => $project['id'])) ?>
+ <?= $this->a(t('Tasks'), 'export', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
- <?= $this->a(t('Daily project summary'), 'project', 'exportDailyProjectSummary', array('project_id' => $project['id'])) ?>
+ <?= $this->a(t('Subtasks'), 'export', 'subtasks', array('project_id' => $project['id'])) ?>
+ </li>
+ <li>
+ <?= $this->a(t('Daily project summary'), 'export', 'summary', array('project_id' => $project['id'])) ?>
</li>
</ul>
<?php endif ?>
diff --git a/docs/cli.markdown b/docs/cli.markdown
index 954b5299..0e2a0203 100644
--- a/docs/cli.markdown
+++ b/docs/cli.markdown
@@ -33,6 +33,7 @@ Available commands:
list Lists commands
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
notification
notification:overdue-tasks Send notifications for overdue tasks
@@ -43,6 +44,20 @@ projects
Available commands
------------------
+### Subtasks CSV export
+
+Usage:
+
+```bash
+./kanboard export:subtasks <project_id> <start_date> <end_date>
+```
+
+Example:
+
+```bash
+./kanboard export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv
+```
+
### Tasks CSV export
Usage:
diff --git a/kanboard b/kanboard
index 6c6d88a2..7a9e648b 100755
--- a/kanboard
+++ b/kanboard
@@ -7,6 +7,7 @@ use Symfony\Component\Console\Application;
$application = new Application('Kanboard', APP_VERSION);
$application->add(new Console\TaskOverdueNotification($container));
+$application->add(new Console\SubtaskExport($container));
$application->add(new Console\TaskExport($container));
$application->add(new Console\ProjectDailySummaryCalculation($container));
$application->add(new Console\ProjectDailySummaryExport($container));