Display tasks in the calendar + improve settings

This commit is contained in:
Frederic Guillot
2015-05-16 21:04:46 -04:00
parent b028b3586c
commit e94a2f6a00
35 changed files with 706 additions and 151 deletions

View File

@@ -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'));
}
$subtask_forcast = $this->config->get('subtask_forecast') == 1 ? $this->subtaskForecast->getCalendarEvents($user_id, $end) : array();
// Subtasks time tracking
if ($this->config->get('calendar_user_subtasks_time_tracking') == 1) {
$events = array_merge($events, $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end));
}
$this->response->json(array_merge($due_tasks, $subtask_timeslots, $subtask_forcast));
// Subtask estimates
if ($this->config->get('calendar_user_subtasks_forecast') == 1) {
$events = array_merge($events, $this->subtaskForecast->getCalendarEvents($user_id, $end));
}
$this->response->json($events);
}
/**

View File

@@ -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)) {
@@ -89,6 +94,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
*
@@ -99,11 +119,24 @@ 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
*

View File

@@ -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>';
}
/**

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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' => '',
);

View File

@@ -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'])),
);
}
}

View File

@@ -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,37 +159,19 @@ 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
*

View File

@@ -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,
)
);
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -7,9 +7,15 @@
<li>
<?= $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>