diff options
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. |