summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.markdown2
-rw-r--r--app/Controller/Calendar.php49
-rw-r--r--app/Controller/Config.php45
-rw-r--r--app/Core/Helper.php2
-rw-r--r--app/Locale/da_DK/translations.php10
-rw-r--r--app/Locale/de_DE/translations.php10
-rw-r--r--app/Locale/es_ES/translations.php10
-rw-r--r--app/Locale/fi_FI/translations.php10
-rw-r--r--app/Locale/fr_FR/translations.php10
-rw-r--r--app/Locale/hu_HU/translations.php10
-rw-r--r--app/Locale/it_IT/translations.php10
-rw-r--r--app/Locale/ja_JP/translations.php10
-rw-r--r--app/Locale/nl_NL/translations.php10
-rw-r--r--app/Locale/pl_PL/translations.php10
-rw-r--r--app/Locale/pt_BR/translations.php10
-rw-r--r--app/Locale/ru_RU/translations.php10
-rw-r--r--app/Locale/sr_Latn_RS/translations.php10
-rw-r--r--app/Locale/sv_SE/translations.php10
-rw-r--r--app/Locale/th_TH/translations.php10
-rw-r--r--app/Locale/tr_TR/translations.php10
-rw-r--r--app/Locale/zh_CN/translations.php10
-rw-r--r--app/Model/Base.php44
-rw-r--r--app/Model/SubtaskTimeTracking.php45
-rw-r--r--app/Model/TaskFilter.php221
-rw-r--r--app/Schema/Mysql.php29
-rw-r--r--app/Schema/Postgres.php29
-rw-r--r--app/Schema/Sqlite.php17
-rw-r--r--app/Template/config/board.php12
-rw-r--r--app/Template/config/calendar.php33
-rw-r--r--app/Template/config/project.php24
-rw-r--r--app/Template/config/sidebar.php6
-rw-r--r--docs/board-configuration.markdown44
-rw-r--r--docs/calendar-settings.markdown42
-rw-r--r--docs/calendar.markdown6
-rw-r--r--docs/project-settings.markdown39
35 files changed, 707 insertions, 152 deletions
diff --git a/README.markdown b/README.markdown
index c003b110..7f9ff1dd 100644
--- a/README.markdown
+++ b/README.markdown
@@ -99,7 +99,9 @@ Documentation
- [Keyboard shortcuts](docs/keyboard-shortcuts.markdown)
- [Application settings](docs/application-configuration.markdown)
+- [Project settings](docs/project-configuration.markdown)
- [Board settings](docs/board-configuration.markdown)
+- [Calendar settings](docs/calendar-configuration.markdown)
- [Link settings](docs/link-labels.markdown)
- [Currency rate](docs/currency-rate.markdown)
- [Config file](docs/config.markdown)
diff --git a/app/Controller/Calendar.php b/app/Controller/Calendar.php
index 49c7f56e..41642a59 100644
--- a/app/Controller/Calendar.php
+++ b/app/Controller/Calendar.php
@@ -47,7 +47,8 @@ class Calendar extends Base
$start = $this->request->getStringParam('start');
$end = $this->request->getStringParam('end');
- $due_tasks = $this->taskFilter
+ // Common filter
+ $filter = $this->taskFilter
->create()
->filterByProject($project_id)
->filterByCategory($this->request->getIntegerParam('category_id', -1))
@@ -55,11 +56,20 @@ class Calendar extends Base
->filterByColumn($this->request->getIntegerParam('column_id', -1))
->filterBySwimlane($this->request->getIntegerParam('swimlane_id', -1))
->filterByColor($this->request->getStringParam('color_id'))
- ->filterByStatus($this->request->getIntegerParam('is_active', -1))
- ->filterByDueDateRange($start, $end)
- ->toCalendarEvents();
+ ->filterByStatus($this->request->getIntegerParam('is_active', -1));
- $this->response->json($due_tasks);
+ // Tasks
+ if ($this->config->get('calendar_project_tasks', 'date_started') === 'date_creation') {
+ $events = $filter->copy()->filterByCreationDateRange($start, $end)->toDateTimeCalendarEvents('date_creation', 'date_completed');
+ }
+ else {
+ $events = $filter->copy()->filterByStartDateRange($start, $end)->toDateTimeCalendarEvents('date_started', 'date_completed');
+ }
+
+ // Tasks with due date
+ $events = array_merge($events, $filter->copy()->filterByDueDateRange($start, $end)->toAllDayCalendarEvents());
+
+ $this->response->json($events);
}
/**
@@ -72,19 +82,30 @@ class Calendar extends Base
$user_id = $this->request->getIntegerParam('user_id');
$start = $this->request->getStringParam('start');
$end = $this->request->getStringParam('end');
+ $filter = $this->taskFilter->create()->filterByOwner($user_id)->filterByStatus(TaskModel::STATUS_OPEN);
- $due_tasks = $this->taskFilter
- ->create()
- ->filterByOwner($user_id)
- ->filterByStatus(TaskModel::STATUS_OPEN)
- ->filterByDueDateRange($start, $end)
- ->toCalendarEvents();
+ // Task with due date
+ $events = $filter->copy()->filterByDueDateRange($start, $end)->toAllDayCalendarEvents();
- $subtask_timeslots = $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end);
+ // Tasks
+ if ($this->config->get('calendar_user_tasks', 'date_started') === 'date_creation') {
+ $events = array_merge($events, $filter->copy()->filterByCreationDateRange($start, $end)->toDateTimeCalendarEvents('date_creation', 'date_completed'));
+ }
+ else {
+ $events = array_merge($events, $filter->copy()->filterByStartDateRange($start, $end)->toDateTimeCalendarEvents('date_started', 'date_completed'));
+ }
+
+ // Subtasks time tracking
+ if ($this->config->get('calendar_user_subtasks_time_tracking') == 1) {
+ $events = array_merge($events, $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end));
+ }
- $subtask_forcast = $this->config->get('subtask_forecast') == 1 ? $this->subtaskForecast->getCalendarEvents($user_id, $end) : array();
+ // Subtask estimates
+ if ($this->config->get('calendar_user_subtasks_forecast') == 1) {
+ $events = array_merge($events, $this->subtaskForecast->getCalendarEvents($user_id, $end));
+ }
- $this->response->json(array_merge($due_tasks, $subtask_timeslots, $subtask_forcast));
+ $this->response->json($events);
}
/**
diff --git a/app/Controller/Config.php b/app/Controller/Config.php
index c17b9f64..fbd374ab 100644
--- a/app/Controller/Config.php
+++ b/app/Controller/Config.php
@@ -40,11 +40,16 @@ class Config extends Base
$values = $this->request->getValues();
- if ($redirect === 'board') {
- $values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'subtask_forecast' => 0);
- }
- else if ($redirect === 'integrations') {
- $values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0);
+ switch ($redirect) {
+ case 'project':
+ $values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0);
+ break;
+ case 'integrations':
+ $values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0);
+ break;
+ case 'calendar':
+ $values += array('calendar_user_subtasks_forecast' => 0, 'calendar_user_subtasks_time_tracking' => 0);
+ break;
}
if ($this->config->save($values)) {
@@ -90,6 +95,21 @@ class Config extends Base
}
/**
+ * Display the project settings page
+ *
+ * @access public
+ */
+ public function project()
+ {
+ $this->common('project');
+
+ $this->response->html($this->layout('config/project', array(
+ 'default_columns' => implode(', ', $this->board->getDefaultColumns()),
+ 'title' => t('Settings').' > '.t('Project settings'),
+ )));
+ }
+
+ /**
* Display the board settings page
*
* @access public
@@ -99,12 +119,25 @@ class Config extends Base
$this->common('board');
$this->response->html($this->layout('config/board', array(
- 'default_columns' => implode(', ', $this->board->getDefaultColumns()),
'title' => t('Settings').' > '.t('Board settings'),
)));
}
/**
+ * Display the calendar settings page
+ *
+ * @access public
+ */
+ public function calendar()
+ {
+ $this->common('calendar');
+
+ $this->response->html($this->layout('config/calendar', array(
+ 'title' => t('Settings').' > '.t('Calendar settings'),
+ )));
+ }
+
+ /**
* Display the integration settings page
*
* @access public
diff --git a/app/Core/Helper.php b/app/Core/Helper.php
index 0650c293..12557e45 100644
--- a/app/Core/Helper.php
+++ b/app/Core/Helper.php
@@ -274,7 +274,7 @@ class Helper
*/
public function formRadio($name, $label, $value, $selected = false, $class = '')
{
- return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->e($value).'" '.($selected ? 'selected="selected"' : '').'> '.$this->e($label).'</label>';
+ return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->e($value).'" '.($selected ? 'checked="checked"' : '').'> '.$this->e($label).'</label>';
}
/**
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index 36d6eb9f..0815440f 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index ee91a3d2..c859d433 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Aufgabe in eine andere Spalte verschieben, wenn ein User zugeordnet wurde.',
'Move the task to another column when assignee is cleared' => 'Aufgabe in eine andere Spalte verschieben, wenn die Zuordnung gelöscht wurde.',
'Source column' => 'Quellspalte',
- 'Show subtask estimates in the user calendar' => 'Teilaufgabenschätzung in Benutzerkalender anzeigen.',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Übergänge',
'Executer' => 'Ausführender',
'Time spent in the column' => 'Zeit in Spalte verbracht',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index a9d8dde7..6f30046c 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Mover la tarea a otra columna al asignarse al usuario',
'Move the task to another column when assignee is cleared' => 'Mover la tarea a otra columna al quitar el asignado',
'Source column' => 'Columna fuente',
- 'Show subtask estimates in the user calendar' => 'Mostrar estimaciones de subtarea en calendario de usuario',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Transiciones',
'Executer' => 'Ejecutor',
'Time spent in the column' => 'Tiempo transcurrido en la columna',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index b975d664..efd7eb6d 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index 03bb59f5..e50bf1b3 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -810,7 +810,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci est assignée à quelqu\'un',
'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée',
'Source column' => 'Colonne d\'origine',
- 'Show subtask estimates in the user calendar' => 'Afficher le temps estimé des sous-tâches dans le calendrier utilisateur',
+ 'Show subtask estimates (forecast of future work)' => 'Afficher l\'estimation des sous-tâches (prévision du travail à venir)',
'Transitions' => 'Transitions',
'Executer' => 'Exécutant',
'Time spent in the column' => 'Temps passé dans la colonne',
@@ -910,4 +910,12 @@ return array(
'Multi-user chat room' => 'Salon de discussion multi-utilisateurs',
'Help on Jabber integration' => 'Aide sur l\'intégration avec Jabber',
'The server address must use this format: "tcp://hostname:5222"' => 'L\'adresse du serveur doit utiliser le format suivant : « tcp://hostname:5222 »',
+ 'Calendar settings' => 'Paramètres du calendrier',
+ 'Project calendar view' => 'Vue en mode projet du calendrier',
+ 'Project settings' => 'Paramètres des projets',
+ 'Show subtasks based on the time tracking' => 'Afficher les sous-tâches basé sur le suivi du temps',
+ 'Show tasks based on the creation date' => 'Afficher les tâches en fonction de la date de création',
+ 'Show tasks based on the start date' => 'Afficher les tâches en fonction de la date de début',
+ 'Subtasks time tracking' => 'Suivi du temps par rapport aux sous-tâches',
+ 'User calendar view' => 'Vue en mode utilisateur du calendrier',
);
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index ceae14bd..7f0280a8 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés után',
'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor',
'Source column' => 'Forrás oszlop',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index a3b5d3a1..3f2f5f76 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Sposta il compito in un\'altra colonna quando viene assegnato ad un utente',
'Move the task to another column when assignee is cleared' => 'Sposta il compito in un\'altra colonna quando l\'assegnatario cancellato',
'Source column' => 'Colonna sorgente',
- 'Show subtask estimates in the user calendar' => 'Mostra le stime dei sotto-compiti nel calendario utente',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Transizioni',
'Executer' => 'Esecutore',
'Time spent in the column' => 'Tempo trascorso nella colonna',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index 0be0c91f..57ba3abb 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'ユーザの割り当てをしたらタスクを他のカラムに移動',
'Move the task to another column when assignee is cleared' => 'ユーザの割り当てがなくなったらタスクを他のカラムに移動',
'Source column' => '移動元のカラム',
- 'Show subtask estimates in the user calendar' => 'カレンダーでサブタスクの見積もりを表示',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => '履歴',
'Executer' => '実行者',
'Time spent in the column' => 'カラムでの時間消費',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php
index c971f95c..f3f2e72b 100644
--- a/app/Locale/nl_NL/translations.php
+++ b/app/Locale/nl_NL/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index 5f035b5d..cb24b60b 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index acf5a6be..652dc80e 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um usuário',
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
'Source column' => 'Coluna de origem',
- 'Show subtask estimates in the user calendar' => 'Mostrar o tempo estimado das subtarefas no calendário do usuário',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Transições',
'Executer' => 'Executor(a)',
'Time spent in the column' => 'Tempo gasto na coluna',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index 37d5c50f..354c6a5b 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Перемещения',
'Executer' => 'Исполнитель',
'Time spent in the column' => 'Время проведенное в колонке',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php
index eec57454..a43fe57b 100644
--- a/app/Locale/sr_Latn_RS/translations.php
+++ b/app/Locale/sr_Latn_RS/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 28addb8c..8c7229f4 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => 'Flytta uppgiften till en annan kolumn när den tilldelats en användare',
'Move the task to another column when assignee is cleared' => 'Flytta uppgiften till en annan kolumn när tilldelningen tas bort.',
'Source column' => 'Källkolumn',
- 'Show subtask estimates in the user calendar' => 'Visa deluppgiftsuppskattning i användarens kalender',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => 'Övergångar',
'Executer' => 'Verkställare',
'Time spent in the column' => 'Tid i kolumnen.',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index 6ce86433..3066e798 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php
index 1daeb36a..e5011905 100644
--- a/app/Locale/tr_TR/translations.php
+++ b/app/Locale/tr_TR/translations.php
@@ -808,7 +808,7 @@ return array(
// 'Move the task to another column when assigned to a user' => '',
// 'Move the task to another column when assignee is cleared' => '',
// 'Source column' => '',
- // 'Show subtask estimates in the user calendar' => '',
+ // 'Show subtask estimates (forecast of future work)' => '',
// 'Transitions' => '',
// 'Executer' => '',
// 'Time spent in the column' => '',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index f5353b2e..c6186145 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -808,7 +808,7 @@ return array(
'Move the task to another column when assigned to a user' => '指定负责人时移动到其它栏目',
'Move the task to another column when assignee is cleared' => '移除负责人时移动到其它栏目',
'Source column' => '原栏目',
- 'Show subtask estimates in the user calendar' => '在用户日历中显示子任务预估',
+ // 'Show subtask estimates (forecast of future work)' => '',
'Transitions' => '变更',
'Executer' => '执行者',
'Time spent in the column' => '栏目中的时间消耗',
@@ -908,4 +908,12 @@ return array(
// 'Multi-user chat room' => '',
// 'Help on Jabber integration' => '',
// 'The server address must use this format: "tcp://hostname:5222"' => '',
+ // 'Calendar settings' => '',
+ // 'Project calendar view' => '',
+ // 'Project settings' => '',
+ // 'Show subtasks based on the time tracking' => '',
+ // 'Show tasks based on the creation date' => '',
+ // 'Show tasks based on the start date' => '',
+ // 'Subtasks time tracking' => '',
+ // 'User calendar view' => '',
);
diff --git a/app/Model/Base.php b/app/Model/Base.php
index b4f9a9e2..dd902bb3 100644
--- a/app/Model/Base.php
+++ b/app/Model/Base.php
@@ -162,4 +162,48 @@ abstract class Base
}
}
}
+
+ /**
+ * Build SQL condition for a given time range
+ *
+ * @access protected
+ * @param string $start_time Start timestamp
+ * @param string $end_time End timestamp
+ * @param string $start_column Start column name
+ * @param string $end_column End column name
+ * @return string
+ */
+ protected function getCalendarCondition($start_time, $end_time, $start_column, $end_column)
+ {
+ $start_column = $this->db->escapeIdentifier($start_column);
+ $end_column = $this->db->escapeIdentifier($end_column);
+
+ $conditions = array(
+ "($start_column >= '$start_time' AND $start_column <= '$end_time')",
+ "($start_column <= '$start_time' AND $end_column >= '$start_time')",
+ "($start_column <= '$start_time' AND ($end_column = '0' OR $end_column IS NULL))",
+ );
+
+ return '('.implode(' OR ', $conditions).')';
+ }
+
+ /**
+ * Get common properties for task calendar events
+ *
+ * @access protected
+ * @param array $task
+ * @return array
+ */
+ protected function getTaskCalendarProperties(array &$task)
+ {
+ return array(
+ 'timezoneParam' => $this->config->getCurrentTimezone(),
+ 'id' => $task['id'],
+ 'title' => t('#%d', $task['id']).' '.$task['title'],
+ 'backgroundColor' => $this->color->getBackgroundColor($task['color_id']),
+ 'borderColor' => $this->color->getBorderColor($task['color_id']),
+ 'textColor' => 'black',
+ 'url' => $this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
+ );
+ }
}
diff --git a/app/Model/SubtaskTimeTracking.php b/app/Model/SubtaskTimeTracking.php
index a984533f..6d4a3467 100644
--- a/app/Model/SubtaskTimeTracking.php
+++ b/app/Model/SubtaskTimeTracking.php
@@ -135,8 +135,13 @@ class SubtaskTimeTracking extends Base
public function getUserCalendarEvents($user_id, $start, $end)
{
$result = $this->getUserQuery($user_id)
- ->addCondition($this->getCalendarCondition($start, $end))
- ->findAll();
+ ->addCondition($this->getCalendarCondition(
+ $this->dateParser->getTimestampFromIsoFormat($start),
+ $this->dateParser->getTimestampFromIsoFormat($end),
+ 'start',
+ 'end'
+ ))
+ ->findAll();
$result = $this->timetable->calculateEventsIntersect($user_id, $result, $start, $end);
@@ -154,38 +159,20 @@ class SubtaskTimeTracking extends Base
*/
public function getProjectCalendarEvents($project_id, $start, $end)
{
- $result = $this->getProjectQuery($project_id)
- ->addCondition($this->getCalendarCondition($start, $end))
- ->findAll();
+ $result = $this
+ ->getProjectQuery($project_id)
+ ->addCondition($this->getCalendarCondition(
+ $this->dateParser->getTimestampFromIsoFormat($start),
+ $this->dateParser->getTimestampFromIsoFormat($end),
+ 'start',
+ 'end'
+ ))
+ ->findAll();
return $this->toCalendarEvents($result);
}
/**
- * Get time slots that should be displayed in the calendar time range
- *
- * @access private
- * @param string $start ISO8601 start date
- * @param string $end ISO8601 end date
- * @return string
- */
- private function getCalendarCondition($start, $end)
- {
- $start_time = $this->dateParser->getTimestampFromIsoFormat($start);
- $end_time = $this->dateParser->getTimestampFromIsoFormat($end);
- $start_column = $this->db->escapeIdentifier('start');
- $end_column = $this->db->escapeIdentifier('end');
-
- $conditions = array(
- "($start_column >= '$start_time' AND $start_column <= '$end_time')",
- "($start_column <= '$start_time' AND $end_column >= '$start_time')",
- "($start_column <= '$start_time' AND $end_column = '0')",
- );
-
- return '('.implode(' OR ', $conditions).')';
- }
-
- /**
* Convert a record set to calendar events
*
* @access private
diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php
index 94f6bab0..21e77e63 100644
--- a/app/Model/TaskFilter.php
+++ b/app/Model/TaskFilter.php
@@ -10,20 +10,59 @@ namespace Model;
*/
class TaskFilter extends Base
{
- private $query;
-
+ /**
+ * Query
+ *
+ * @access public
+ * @var \PicoDb\Table
+ */
+ public $query;
+
+ /**
+ * Create a new query
+ *
+ * @access public
+ * @return TaskFilter
+ */
public function create()
{
$this->query = $this->db->table(Task::TABLE);
return $this;
}
+ /**
+ * Clone the filter
+ *
+ * @access public
+ * @return TaskFilter
+ */
+ public function copy()
+ {
+ $filter = clone($this);
+ $filter->query = clone($this->query);
+ return $filter;
+ }
+
+ /**
+ * Exclude a list of task_id
+ *
+ * @access public
+ * @param array $task_ids
+ * @return TaskFilter
+ */
public function excludeTasks(array $task_ids)
{
$this->query->notin('id', $task_ids);
return $this;
}
+ /**
+ * Filter by id
+ *
+ * @access public
+ * @param integer $task_id
+ * @return TaskFilter
+ */
public function filterById($task_id)
{
if ($task_id > 0) {
@@ -33,18 +72,39 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by title
+ *
+ * @access public
+ * @param string $title
+ * @return TaskFilter
+ */
public function filterByTitle($title)
{
$this->query->ilike('title', '%'.$title.'%');
return $this;
}
+ /**
+ * Filter by a list of project id
+ *
+ * @access public
+ * @param array $project_ids
+ * @return TaskFilter
+ */
public function filterByProjects(array $project_ids)
{
$this->query->in('project_id', $project_ids);
return $this;
}
+ /**
+ * Filter by project id
+ *
+ * @access public
+ * @param integer $project_id
+ * @return TaskFilter
+ */
public function filterByProject($project_id)
{
if ($project_id > 0) {
@@ -54,6 +114,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by category id
+ *
+ * @access public
+ * @param integer $category_id
+ * @return TaskFilter
+ */
public function filterByCategory($category_id)
{
if ($category_id >= 0) {
@@ -63,6 +130,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by assignee
+ *
+ * @access public
+ * @param integer $owner_id
+ * @return TaskFilter
+ */
public function filterByOwner($owner_id)
{
if ($owner_id >= 0) {
@@ -72,6 +146,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by color
+ *
+ * @access public
+ * @param string $color_id
+ * @return TaskFilter
+ */
public function filterByColor($color_id)
{
if ($color_id !== '') {
@@ -81,6 +162,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by column
+ *
+ * @access public
+ * @param integer $column_id
+ * @return TaskFilter
+ */
public function filterByColumn($column_id)
{
if ($column_id >= 0) {
@@ -90,6 +178,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by swimlane
+ *
+ * @access public
+ * @param integer $swimlane_id
+ * @return TaskFilter
+ */
public function filterBySwimlane($swimlane_id)
{
if ($swimlane_id >= 0) {
@@ -99,6 +194,13 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by status
+ *
+ * @access public
+ * @param integer $is_active
+ * @return TaskFilter
+ */
public function filterByStatus($is_active)
{
if ($is_active >= 0) {
@@ -108,6 +210,14 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by due date (range)
+ *
+ * @access public
+ * @param integer $start
+ * @param integer $end
+ * @return TaskFilter
+ */
public function filterByDueDateRange($start, $end)
{
$this->query->gte('date_due', $this->dateParser->getTimestampFromIsoFormat($start));
@@ -116,11 +226,63 @@ class TaskFilter extends Base
return $this;
}
+ /**
+ * Filter by start date (range)
+ *
+ * @access public
+ * @param integer $start
+ * @param integer $end
+ * @return TaskFilter
+ */
+ public function filterByStartDateRange($start, $end)
+ {
+ $this->query->addCondition($this->getCalendarCondition(
+ $this->dateParser->getTimestampFromIsoFormat($start),
+ $this->dateParser->getTimestampFromIsoFormat($end),
+ 'date_started',
+ 'date_completed'
+ ));
+
+ return $this;
+ }
+
+ /**
+ * Filter by creation date
+ *
+ * @access public
+ * @param integer $start
+ * @param integer $end
+ * @return TaskFilter
+ */
+ public function filterByCreationDateRange($start, $end)
+ {
+ $this->query->addCondition($this->getCalendarCondition(
+ $this->dateParser->getTimestampFromIsoFormat($start),
+ $this->dateParser->getTimestampFromIsoFormat($end),
+ 'date_creation',
+ 'date_completed'
+ ));
+
+ return $this;
+ }
+
+ /**
+ * Get all results of the filter
+ *
+ * @access public
+ * @return array
+ */
public function findAll()
{
return $this->query->findAll();
}
+ /**
+ * Format the results to the ajax autocompletion
+ *
+ * @access public
+ * @return array
+ */
public function toAutoCompletion()
{
return $this->query->columns('id', 'title')->filter(function(array $results) {
@@ -135,22 +297,53 @@ class TaskFilter extends Base
})->findAll();
}
- public function toCalendarEvents()
+ /**
+ * Transform results to calendar events
+ *
+ * @access public
+ * @param string $start_column Column name for the start date
+ * @param string $end_column Column name for the end date
+ * @return array
+ */
+ public function toDateTimeCalendarEvents($start_column, $end_column)
{
$events = array();
foreach ($this->query->findAll() as $task) {
- $events[] = array(
- 'timezoneParam' => $this->config->getCurrentTimezone(),
- 'id' => $task['id'],
- 'title' => t('#%d', $task['id']).' '.$task['title'],
- 'start' => date('Y-m-d', $task['date_due']),
- 'end' => date('Y-m-d', $task['date_due']),
- 'allday' => true,
- 'backgroundColor' => $this->color->getBackgroundColor($task['color_id']),
- 'borderColor' => $this->color->getBorderColor($task['color_id']),
- 'textColor' => 'black',
- 'url' => $this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
+
+ $events[] = array_merge(
+ $this->getTaskCalendarProperties($task),
+ array(
+ 'start' => date('Y-m-d\TH:i:s', $task[$start_column]),
+ 'end' => date('Y-m-d\TH:i:s', $task[$end_column] ?: time()),
+ 'editable' => false,
+ )
+ );
+ }
+
+ return $events;
+ }
+
+ /**
+ * Transform results to all day calendar events
+ *
+ * @access public
+ * @param string $column Column name for the date
+ * @return array
+ */
+ public function toAllDayCalendarEvents($column = 'date_due')
+ {
+ $events = array();
+
+ foreach ($this->query->findAll() as $task) {
+
+ $events[] = array_merge(
+ $this->getTaskCalendarProperties($task),
+ array(
+ 'start' => date('Y-m-d', $task[$column]),
+ 'end' => date('Y-m-d', $task[$column]),
+ 'allday' => true,
+ )
);
}
diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php
index 369d4826..7195c7fe 100644
--- a/app/Schema/Mysql.php
+++ b/app/Schema/Mysql.php
@@ -6,7 +6,22 @@ use PDO;
use Core\Security;
use Model\Link;
-const VERSION = 68;
+const VERSION = 69;
+
+function version_69($pdo)
+{
+ $rq = $pdo->prepare("SELECT `value` FROM `settings` WHERE `option`='subtask_forecast'");
+ $rq->execute();
+ $result = $rq->fetch(PDO::FETCH_ASSOC);
+
+ $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
+ $rq->execute(array('calendar_user_subtasks_forecast', isset($result['subtask_forecast']) && $result['subtask_forecast'] == 1 ? 1 : 0));
+ $rq->execute(array('calendar_user_subtasks_time_tracking', 0));
+ $rq->execute(array('calendar_user_tasks', 'date_started'));
+ $rq->execute(array('calendar_project_tasks', 'date_started'));
+
+ $pdo->exec("DELETE FROM `settings` WHERE `option`='subtask_forecast'");
+}
function version_68($pdo)
{
@@ -20,12 +35,12 @@ function version_68($pdo)
$rq->execute(array('integration_jabber_room', ''));
$pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber INTEGER DEFAULT '0'");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname TEXT DEFAULT 'kanboard'");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room TEXT DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname VARCHAR(255) DEFAULT 'kanboard'");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room VARCHAR(255) DEFAULT ''");
}
function version_67($pdo)
diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php
index 1cd0ab8f..27efe8c4 100644
--- a/app/Schema/Postgres.php
+++ b/app/Schema/Postgres.php
@@ -6,7 +6,22 @@ use PDO;
use Core\Security;
use Model\Link;
-const VERSION = 49;
+const VERSION = 50;
+
+function version_50($pdo)
+{
+ $rq = $pdo->prepare("SELECT value FROM settings WHERE option='subtask_forecast'");
+ $rq->execute();
+ $result = $rq->fetch(PDO::FETCH_ASSOC);
+
+ $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
+ $rq->execute(array('calendar_user_subtasks_forecast', isset($result['subtask_forecast']) && $result['subtask_forecast'] == 1 ? 1 : 0));
+ $rq->execute(array('calendar_user_subtasks_time_tracking', 0));
+ $rq->execute(array('calendar_user_tasks', 'date_started'));
+ $rq->execute(array('calendar_project_tasks', 'date_started'));
+
+ $pdo->exec("DELETE FROM settings WHERE option='subtask_forecast'");
+}
function version_49($pdo)
{
@@ -20,12 +35,12 @@ function version_49($pdo)
$rq->execute(array('integration_jabber_room', ''));
$pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber INTEGER DEFAULT '0'");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password TEXT DEFAULT ''");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname TEXT DEFAULT 'kanboard'");
- $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room TEXT DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password VARCHAR(255) DEFAULT ''");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname VARCHAR(255) DEFAULT 'kanboard'");
+ $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room VARCHAR(255) DEFAULT ''");
}
function version_48($pdo)
diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php
index 830fd916..7af7bbe8 100644
--- a/app/Schema/Sqlite.php
+++ b/app/Schema/Sqlite.php
@@ -6,7 +6,22 @@ use Core\Security;
use PDO;
use Model\Link;
-const VERSION = 67;
+const VERSION = 68;
+
+function version_68($pdo)
+{
+ $rq = $pdo->prepare("SELECT value FROM settings WHERE option='subtask_forecast'");
+ $rq->execute();
+ $result = $rq->fetch(PDO::FETCH_ASSOC);
+
+ $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
+ $rq->execute(array('calendar_user_subtasks_forecast', isset($result['subtask_forecast']) && $result['subtask_forecast'] == 1 ? 1 : 0));
+ $rq->execute(array('calendar_user_subtasks_time_tracking', 0));
+ $rq->execute(array('calendar_user_tasks', 'date_started'));
+ $rq->execute(array('calendar_project_tasks', 'date_started'));
+
+ $pdo->exec("DELETE FROM settings WHERE option='subtask_forecast'");
+}
function version_67($pdo)
{
diff --git a/app/Template/config/board.php b/app/Template/config/board.php
index 15e2b422..c55003de 100644
--- a/app/Template/config/board.php
+++ b/app/Template/config/board.php
@@ -18,18 +18,6 @@
<?= $this->formNumber('board_private_refresh_interval', $values, $errors) ?><br/>
<p class="form-help"><?= t('Frequency in second (0 to disable this feature, 10 seconds by default)') ?></p>
- <?= $this->formLabel(t('Default columns for new projects (Comma-separated)'), 'board_columns') ?>
- <?= $this->formText('board_columns', $values, $errors) ?><br/>
- <p class="form-help"><?= t('Default values are "%s"', $default_columns) ?></p>
-
- <?= $this->formLabel(t('Default categories for new projects (Comma-separated)'), 'project_categories') ?>
- <?= $this->formText('project_categories', $values, $errors) ?><br/>
- <p class="form-help"><?= t('Example: "Bug, Feature Request, Improvement"') ?></p>
-
- <?= $this->formCheckbox('subtask_restriction', t('Allow only one subtask in progress at the same time for a user'), 1, $values['subtask_restriction'] == 1) ?>
- <?= $this->formCheckbox('subtask_time_tracking', t('Enable time tracking for subtasks'), 1, $values['subtask_time_tracking'] == 1) ?>
- <?= $this->formCheckbox('subtask_forecast', t('Show subtask estimates in the user calendar'), 1, $values['subtask_forecast'] == 1) ?>
-
<div class="form-actions">
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
</div>
diff --git a/app/Template/config/calendar.php b/app/Template/config/calendar.php
new file mode 100644
index 00000000..300d3419
--- /dev/null
+++ b/app/Template/config/calendar.php
@@ -0,0 +1,33 @@
+<div class="page-header">
+ <h2><?= t('Calendar settings') ?></h2>
+</div>
+<section>
+<form method="post" action="<?= $this->u('config', 'calendar') ?>" autocomplete="off">
+
+ <?= $this->formCsrf() ?>
+
+ <h3><?= t('Project calendar view') ?></h3>
+ <div class="listing">
+ <?= $this->formRadios('calendar_project_tasks', array(
+ 'date_creation' => t('Show tasks based on the creation date'),
+ 'date_started' => t('Show tasks based on the start date'),
+ ), $values) ?>
+ </div>
+
+ <h3><?= t('User calendar view') ?></h3>
+ <div class="listing">
+ <?= $this->formRadios('calendar_user_tasks', array(
+ 'date_creation' => t('Show tasks based on the creation date'),
+ 'date_started' => t('Show tasks based on the start date'),
+ ), $values) ?>
+
+ <h4><?= t('Subtasks time tracking') ?></h4>
+ <?= $this->formCheckbox('calendar_user_subtasks_time_tracking', t('Show subtasks based on the time tracking'), 1, $values['calendar_user_subtasks_time_tracking'] == 1) ?>
+ <?= $this->formCheckbox('calendar_user_subtasks_forecast', t('Show subtask estimates (forecast of future work)'), 1, $values['calendar_user_subtasks_forecast'] == 1) ?>
+ </div>
+
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
+ </div>
+</form>
+</section> \ No newline at end of file
diff --git a/app/Template/config/project.php b/app/Template/config/project.php
new file mode 100644
index 00000000..b559d632
--- /dev/null
+++ b/app/Template/config/project.php
@@ -0,0 +1,24 @@
+<div class="page-header">
+ <h2><?= t('Project settings') ?></h2>
+</div>
+<section>
+<form method="post" action="<?= $this->u('config', 'project') ?>" autocomplete="off">
+
+ <?= $this->formCsrf() ?>
+
+ <?= $this->formLabel(t('Default columns for new projects (Comma-separated)'), 'board_columns') ?>
+ <?= $this->formText('board_columns', $values, $errors) ?><br/>
+ <p class="form-help"><?= t('Default values are "%s"', $default_columns) ?></p>
+
+ <?= $this->formLabel(t('Default categories for new projects (Comma-separated)'), 'project_categories') ?>
+ <?= $this->formText('project_categories', $values, $errors) ?><br/>
+ <p class="form-help"><?= t('Example: "Bug, Feature Request, Improvement"') ?></p>
+
+ <?= $this->formCheckbox('subtask_restriction', t('Allow only one subtask in progress at the same time for a user'), 1, $values['subtask_restriction'] == 1) ?>
+ <?= $this->formCheckbox('subtask_time_tracking', t('Enable time tracking for subtasks'), 1, $values['subtask_time_tracking'] == 1) ?>
+
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
+ </div>
+</form>
+</section> \ No newline at end of file
diff --git a/app/Template/config/sidebar.php b/app/Template/config/sidebar.php
index a4f9d8e3..4bae9e2e 100644
--- a/app/Template/config/sidebar.php
+++ b/app/Template/config/sidebar.php
@@ -8,9 +8,15 @@
<?= $this->a(t('Application settings'), 'config', 'application') ?>
</li>
<li>
+ <?= $this->a(t('Project settings'), 'config', 'project') ?>
+ </li>
+ <li>
<?= $this->a(t('Board settings'), 'config', 'board') ?>
</li>
<li>
+ <?= $this->a(t('Calendar settings'), 'config', 'calendar') ?>
+ </li>
+ <li>
<?= $this->a(t('Link settings'), 'link', 'index') ?>
</li>
<li>
diff --git a/docs/board-configuration.markdown b/docs/board-configuration.markdown
index dda9787f..1c5ff51a 100644
--- a/docs/board-configuration.markdown
+++ b/docs/board-configuration.markdown
@@ -1,8 +1,5 @@
Board settings
-===============
-
-Some parameters for boards can be changed on the settings page.
-Only administrators can change those settings.
+==============
Go to the menu **Settings**, then choose **Board settings** on the left.
@@ -25,42 +22,3 @@ When you share a board, the page will refresh automatically every 60 seconds by
When your web browser is open on a board, Kanboard check every 10 seconds if something have been changed by someone else.
Technically this process is done by Ajax polling.
-
-### Default columns for new projects
-
-You can change the default column names here.
-It's useful if you always create projects with the same columns.
-
-Each column name must be separated by a comma.
-
-By default, Kanboard use those column names: Backlog, Ready, Work in progress and Done.
-
-### Default categories for new projects
-
-Categories are not global to the application but attached to a project.
-Each project can have different categories.
-
-However, if you always create the same categories for all your projects, you can define here the list of categories to create automatically.
-
-### Allow only one subtask in progress at the same time for a user
-
-When this option is enabled, a user can work with only one subtask at the time.
-
-If another subtask have the status "in progress", the user will see this dialog box:
-
-![Subtask user restriction](http://kanboard.net/screenshots/documentation/subtask-user-restriction.png)
-
-### Enable time tracking for subtasks
-
-When this option is enabled, each time the status of a subtask is changed, the start time and the end time are recorded in the database for the assignee.
-
-- When the status changes to "in progress" then the start time is saved
-- When the status changes to "done" then the end time is saved
-
-The time spent for the subtask and the task is also updated.
-
-### Show subtask estimates in the user calendar
-
-When enabled, assigned subtasks with the status "todo" and with a defined estimate value will be displayed on the user calendar.
-
-The user calender is available on the dashboard or from the user profile. \ No newline at end of file
diff --git a/docs/calendar-settings.markdown b/docs/calendar-settings.markdown
new file mode 100644
index 00000000..c69c9b85
--- /dev/null
+++ b/docs/calendar-settings.markdown
@@ -0,0 +1,42 @@
+Calendar settings
+=================
+
+Go to the menu **Settings**, then choose **Calendar settings** on the left.
+
+![Calendar settings](http://kanboard.net/screenshots/documentation/calendar-settings.png)
+
+There are two different calendars in Kanboard:
+
+- Project calendar
+- User calendar (available from the dashboard)
+
+Project calendar
+----------------
+
+This calendar show tasks with defined due date and tasks based on the creation date or the start date.
+
+### Show tasks based on the creation date
+
+The start date of the calendar event is the creation date of the task.
+The end date of the event is the date of completion.
+
+### Show tasks based on the start date
+
+The start date of the calendar event is the start date of the task.
+This date can be defined manually.
+The end date of the event is the date of completion.
+If there is no start date the task will not appear on the calendar.
+
+User calendar
+-------------
+
+This calendar show only tasks assigned to the user and optionally subtasks information.
+
+### Show subtasks based on the time tracking
+
+Display subtasks in the calendar from the information recorded in the time tracking table.
+The intersection with the user timetable is also calculated.
+
+### Show subtask estimates (forecast of future work)
+
+Display the estimate of future work for subtasks in status "todo" and with a defined "estimate" value.
diff --git a/docs/calendar.markdown b/docs/calendar.markdown
index 7b5be5fb..1dd4a08a 100644
--- a/docs/calendar.markdown
+++ b/docs/calendar.markdown
@@ -9,6 +9,10 @@ There are two different views for the calendar:
At this time the calendar is able to display these information:
- Tasks with a due date, displayed at the top. The date can be changed by moving the task to another day.
-- Subtask time tracking, each recorded time slot will be shown in the calendar.
+- Tasks based on the creation date or the start date. These events cannot be modified with the calendar.
+- Subtask time tracking, all recorded time slot will be shown in the calendar.
+- Subtask estimates, forecast of work left
![Calendar](http://kanboard.net/screenshots/documentation/calendar.png)
+
+The calendar configuration can be changed in the settings page.
diff --git a/docs/project-settings.markdown b/docs/project-settings.markdown
new file mode 100644
index 00000000..5cfa4974
--- /dev/null
+++ b/docs/project-settings.markdown
@@ -0,0 +1,39 @@
+Project settings
+================
+
+Go to the menu **Settings**, then choose **Project settings** on the left.
+
+![Project settings](http://kanboard.net/screenshots/documentation/project-settings.png)
+
+### Default columns for new projects
+
+You can change the default column names here.
+It's useful if you always create projects with the same columns.
+
+Each column name must be separated by a comma.
+
+By default, Kanboard use those column names: Backlog, Ready, Work in progress and Done.
+
+### Default categories for new projects
+
+Categories are not global to the application but attached to a project.
+Each project can have different categories.
+
+However, if you always create the same categories for all your projects, you can define here the list of categories to create automatically.
+
+### Allow only one subtask in progress at the same time for a user
+
+When this option is enabled, a user can work with only one subtask at the time.
+
+If another subtask have the status "in progress", the user will see this dialog box:
+
+![Subtask user restriction](http://kanboard.net/screenshots/documentation/subtask-user-restriction.png)
+
+### Enable time tracking for subtasks
+
+When this option is enabled, each time the status of a subtask is changed, the start time and the end time are recorded in the database for the assignee.
+
+- When the status changes to "in progress" then the start time is saved
+- When the status changes to "done" then the end time is saved
+
+The time spent for the subtask and the task is also updated.