diff options
49 files changed, 401 insertions, 19 deletions
@@ -4,6 +4,7 @@ Version 1.0.25 (unreleased) New features: * Add project owner (Directly Responsible Individual) +* Add configurable task priority Version 1.0.24 -------------- diff --git a/app/Controller/ProjectEdit.php b/app/Controller/ProjectEdit.php index 3b0a3da3..0dfc7de3 100644 --- a/app/Controller/ProjectEdit.php +++ b/app/Controller/ProjectEdit.php @@ -41,6 +41,16 @@ class ProjectEdit extends Base } /** + * Change task priority + * + * @access public + */ + public function priority(array $values = array(), array $errors = array()) + { + $this->renderView('project_edit/task_priority', $values, $errors); + } + + /** * Validate and update a project * * @access public diff --git a/app/Controller/Taskcreation.php b/app/Controller/Taskcreation.php index 4d74fac6..49ccea7f 100644 --- a/app/Controller/Taskcreation.php +++ b/app/Controller/Taskcreation.php @@ -32,6 +32,7 @@ class Taskcreation extends Base } $this->response->html($this->template->$method('task_creation/form', array( + 'project' => $project, 'ajax' => $this->request->isAjax(), 'errors' => $errors, 'values' => $values + array('project_id' => $project['id']), diff --git a/app/Controller/Taskmodification.php b/app/Controller/Taskmodification.php index 81cf430f..2c97970b 100644 --- a/app/Controller/Taskmodification.php +++ b/app/Controller/Taskmodification.php @@ -98,6 +98,7 @@ class Taskmodification extends Base public function edit(array $values = array(), array $errors = array()) { $task = $this->getTask(); + $project = $this->project->getById($task['project_id']); $ajax = $this->request->isAjax(); if (empty($values)) { @@ -107,6 +108,7 @@ class Taskmodification extends Base $this->dateParser->format($values, array('date_due')); $params = array( + 'project' => $project, 'values' => $values, 'errors' => $errors, 'task' => $task, diff --git a/app/Helper/Task.php b/app/Helper/Task.php index 1405a167..500b8a89 100644 --- a/app/Helper/Task.php +++ b/app/Helper/Task.php @@ -2,13 +2,15 @@ namespace Kanboard\Helper; +use Kanboard\Core\Base; + /** * Task helpers * * @package helper * @author Frederic Guillot */ -class Task extends \Kanboard\Core\Base +class Task extends Base { public function getColors() { @@ -34,4 +36,33 @@ class Task extends \Kanboard\Core\Base { return $this->taskPermission->canRemoveTask($task); } + + public function selectPriority(array $project, array $values) + { + $html = ''; + + if ($project['priority_end'] > $project['priority_start']) { + $range = range($project['priority_start'], $project['priority_end']); + $options = array_combine($range, $range); + $values += array('priority' => $project['priority_default']); + + $html .= $this->helper->form->label(t('Priority'), 'priority'); + $html .= $this->helper->form->select('priority', $options, $values, array(), array('tabindex="7"')); + } + + return $html; + } + + public function formatPriority(array $project, array $task) + { + $html = ''; + + if ($project['priority_end'] > $project['priority_start']) { + $html .= '<span class="task-board-priority" title="'.t('Task priority').'">'; + $html .= $task['priority'] >= 0 ? 'P'.$task['priority'] : '-P'.abs($task['priority']); + $html .= '</span>'; + } + + return $html; + } } diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index e1af1c08..90ab1296 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index b93b7c23..83d88f35 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 63850d70..7a82bc1e 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index ef056972..1158dd67 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 91709476..16c96ec5 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index c887e02d..cde825e2 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index f36ce104..32110e1c 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1112,4 +1112,13 @@ return array( 'Those dates are useful for the project Gantt chart.' => 'Ces dates sont utiles pour le diagramme de Gantt des projets.', 'Private projects do not have users and groups management.' => 'Les projets privés n\'ont pas de gestion d\'utilisateurs et de groupes.', 'There is no project member.' => 'Il y a aucun membre du projet.', + 'Priority' => 'Priorité', + 'Task priority' => 'Priorité des tâches', + 'General' => 'Général', + 'Dates' => 'Dates', + 'Default priority' => 'Priorité par défaut', + 'Lowest priority' => 'Priorité basse', + 'Highest priority' => 'Priorité haute', + 'If you put zero to the low and high priority, this feature will be disabled.' => 'Si vous mettez zéro pour la priorité basse et haute, cette fonctionnalité sera désactivée.', + 'Priority: %d' => 'Priorité : %d', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index e12a7aad..25d55bb2 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index 49d61d58..e3316405 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 5e2c32a9..1e32213f 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index f1884b93..b9cde718 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 65aaa4e3..43c288c7 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 520149d5..682f44a8 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 87f5323e..4f38f256 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 37dcfe3d..ee0ceb47 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index 6e47c514..09e87048 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index f57657ee..19c2ebf7 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 02bf9934..d09258ed 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index c779cd6c..2b3553c2 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index ca412273..1c01e94d 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index b2b9a55b..e0de5844 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 17163f45..c4da560d 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index e4b732ef..e0b90b58 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1109,4 +1109,13 @@ return array( // 'Those dates are useful for the project Gantt chart.' => '', // 'Private projects do not have users and groups management.' => '', // 'There is no project member.' => '', + // 'Priority' => '', + // 'Task priority' => '', + // 'General' => '', + // 'Dates' => '', + // 'Default priority' => '', + // 'Lowest priority' => '', + // 'Highest priority' => '', + // 'If you put zero to the low and high priority, this feature will be disabled.' => '', + // 'Priority: %d' => '', ); diff --git a/app/Model/Project.php b/app/Model/Project.php index ba0716b0..d0a8bfc8 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -334,6 +334,8 @@ class Project extends Base $values['identifier'] = strtoupper($values['identifier']); } + $this->convertIntegerFields($values, array('priority_default', 'priority_start', 'priority_end')); + if (! $this->db->table(self::TABLE)->save($values)) { $this->db->cancelTransaction(); return false; @@ -400,6 +402,8 @@ class Project extends Base $values['identifier'] = strtoupper($values['identifier']); } + $this->convertIntegerFields($values, array('priority_default', 'priority_start', 'priority_end')); + return $this->exists($values['id']) && $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); } diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 836fbe46..1c83136b 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -113,6 +113,7 @@ class TaskFinder extends Base 'tasks.is_active', 'tasks.score', 'tasks.category_id', + 'tasks.priority', 'tasks.date_moved', 'tasks.recurrence_status', 'tasks.recurrence_trigger', @@ -308,6 +309,7 @@ class TaskFinder extends Base tasks.is_active, tasks.score, tasks.category_id, + tasks.priority, tasks.swimlane_id, tasks.date_moved, tasks.recurrence_status, diff --git a/app/Model/TaskModification.php b/app/Model/TaskModification.php index a0ad292c..eee7b2e0 100644 --- a/app/Model/TaskModification.php +++ b/app/Model/TaskModification.php @@ -88,7 +88,7 @@ class TaskModification extends Base $this->dateParser->convert($values, array('date_started'), true); $this->removeFields($values, array('another_task', 'id')); $this->resetFields($values, array('date_due', 'date_started', 'score', 'category_id', 'time_estimated', 'time_spent')); - $this->convertIntegerFields($values, array('is_active', 'recurrence_status', 'recurrence_trigger', 'recurrence_factor', 'recurrence_timeframe', 'recurrence_basedate')); + $this->convertIntegerFields($values, array('priority', 'is_active', 'recurrence_status', 'recurrence_trigger', 'recurrence_factor', 'recurrence_timeframe', 'recurrence_basedate')); $values['date_modification'] = time(); } diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index ad7f7be1..8f1db510 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,15 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 102; +const VERSION = 103; + +function version_103(PDO $pdo) +{ + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_default INT DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_start INT DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_end INT DEFAULT 3"); + $pdo->exec("ALTER TABLE tasks ADD COLUMN priority INT DEFAULT 0"); +} function version_102(PDO $pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index d23a7723..a7bf8054 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,15 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 82; +const VERSION = 83; + +function version_83(PDO $pdo) +{ + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_default INTEGER DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_start INTEGER DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_end INTEGER DEFAULT 3"); + $pdo->exec("ALTER TABLE tasks ADD COLUMN priority INTEGER DEFAULT 0"); +} function version_82(PDO $pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index daa70f54..08689749 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,15 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 94; +const VERSION = 95; + +function version_95(PDO $pdo) +{ + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_default INTEGER DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_start INTEGER DEFAULT 0"); + $pdo->exec("ALTER TABLE projects ADD COLUMN priority_end INTEGER DEFAULT 3"); + $pdo->exec("ALTER TABLE tasks ADD COLUMN priority INTEGER DEFAULT 0"); +} function version_94(PDO $pdo) { diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 5a5c8652..057a1b3c 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -64,6 +64,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('project/:project_id/edit', 'ProjectEdit', 'edit'); $container['route']->addRoute('project/:project_id/edit/dates', 'ProjectEdit', 'dates'); $container['route']->addRoute('project/:project_id/edit/description', 'ProjectEdit', 'description'); + $container['route']->addRoute('project/:project_id/edit/priority', 'ProjectEdit', 'priority'); // ProjectUser routes $container['route']->addRoute('projects/managers/:user_id', 'projectuser', 'managers'); diff --git a/app/Template/board/task_footer.php b/app/Template/board/task_footer.php index 4a16364c..26f3b1d4 100644 --- a/app/Template/board/task_footer.php +++ b/app/Template/board/task_footer.php @@ -69,4 +69,6 @@ <i class="fa fa-flag flag-milestone"></i> </span> <?php endif ?> + + <?= $this->task->formatPriority($project, $task) ?> </div> diff --git a/app/Template/board/task_private.php b/app/Template/board/task_private.php index 8d76453c..4880af00 100644 --- a/app/Template/board/task_private.php +++ b/app/Template/board/task_private.php @@ -78,6 +78,7 @@ <?= $this->render('board/task_footer', array( 'task' => $task, 'not_editable' => $not_editable, + 'project' => $project, )) ?> </div> <?php endif ?> diff --git a/app/Template/board/task_public.php b/app/Template/board/task_public.php index bacdcef4..d02722bb 100644 --- a/app/Template/board/task_public.php +++ b/app/Template/board/task_public.php @@ -25,5 +25,6 @@ <?= $this->render('board/task_footer', array( 'task' => $task, 'not_editable' => $not_editable, + 'project' => $project, )) ?> </div>
\ No newline at end of file diff --git a/app/Template/project_edit/dates.php b/app/Template/project_edit/dates.php index d3f4bad8..cb585c6a 100644 --- a/app/Template/project_edit/dates.php +++ b/app/Template/project_edit/dates.php @@ -4,6 +4,7 @@ <li ><?= $this->url->link(t('General'), 'ProjectEdit', 'edit', array('project_id' => $project['id'])) ?></li> <li class="active"><?= $this->url->link(t('Dates'), 'ProjectEdit', 'dates', array('project_id' => $project['id'])) ?></li> <li><?= $this->url->link(t('Description'), 'ProjectEdit', 'description', array('project_id' => $project['id'])) ?></li> + <li><?= $this->url->link(t('Task priority'), 'ProjectEdit', 'priority', array('project_id' => $project['id'])) ?></li> </ul> </div> <form method="post" action="<?= $this->url->href('ProjectEdit', 'update', array('project_id' => $project['id'], 'redirect' => 'dates')) ?>" autocomplete="off"> diff --git a/app/Template/project_edit/description.php b/app/Template/project_edit/description.php index 3af484d5..dce8ab10 100644 --- a/app/Template/project_edit/description.php +++ b/app/Template/project_edit/description.php @@ -4,6 +4,7 @@ <li><?= $this->url->link(t('General'), 'ProjectEdit', 'edit', array('project_id' => $project['id'])) ?></li> <li><?= $this->url->link(t('Dates'), 'ProjectEdit', 'dates', array('project_id' => $project['id'])) ?></li> <li class="active"><?= $this->url->link(t('Description'), 'ProjectEdit', 'description', array('project_id' => $project['id'])) ?></li> + <li><?= $this->url->link(t('Task priority'), 'ProjectEdit', 'priority', array('project_id' => $project['id'])) ?></li> </ul> </div> <form method="post" action="<?= $this->url->href('ProjectEdit', 'update', array('project_id' => $project['id'], 'redirect' => 'description')) ?>" autocomplete="off"> diff --git a/app/Template/project_edit/general.php b/app/Template/project_edit/general.php index 1da913da..5caefa2d 100644 --- a/app/Template/project_edit/general.php +++ b/app/Template/project_edit/general.php @@ -4,6 +4,7 @@ <li class="active"><?= $this->url->link(t('General'), 'ProjectEdit', 'edit', array('project_id' => $project['id'])) ?></li> <li><?= $this->url->link(t('Dates'), 'ProjectEdit', 'dates', array('project_id' => $project['id'])) ?></li> <li><?= $this->url->link(t('Description'), 'ProjectEdit', 'description', array('project_id' => $project['id'])) ?></li> + <li><?= $this->url->link(t('Task priority'), 'ProjectEdit', 'priority', array('project_id' => $project['id'])) ?></li> </ul> </div> <form method="post" action="<?= $this->url->href('ProjectEdit', 'update', array('project_id' => $project['id'], 'redirect' => 'edit')) ?>" autocomplete="off"> diff --git a/app/Template/project_edit/task_priority.php b/app/Template/project_edit/task_priority.php new file mode 100644 index 00000000..e54215b2 --- /dev/null +++ b/app/Template/project_edit/task_priority.php @@ -0,0 +1,29 @@ +<div class="page-header"> + <h2><?= t('Edit project') ?></h2> + <ul> + <li ><?= $this->url->link(t('General'), 'ProjectEdit', 'edit', array('project_id' => $project['id'])) ?></li> + <li><?= $this->url->link(t('Dates'), 'ProjectEdit', 'dates', array('project_id' => $project['id'])) ?></li> + <li><?= $this->url->link(t('Description'), 'ProjectEdit', 'description', array('project_id' => $project['id'])) ?></li> + <li class="active"><?= $this->url->link(t('Task priority'), 'ProjectEdit', 'priority', array('project_id' => $project['id'])) ?></li> + </ul> +</div> +<form method="post" action="<?= $this->url->href('ProjectEdit', 'update', array('project_id' => $project['id'], 'redirect' => 'priority')) ?>" autocomplete="off"> + <?= $this->form->csrf() ?> + <?= $this->form->hidden('id', $values) ?> + <?= $this->form->hidden('name', $values) ?> + + <?= $this->form->label(t('Default priority'), 'priority_default') ?> + <?= $this->form->number('priority_default', $values, $errors) ?> + + <?= $this->form->label(t('Lowest priority'), 'priority_start') ?> + <?= $this->form->number('priority_start', $values, $errors) ?> + + <?= $this->form->label(t('Highest priority'), 'priority_end') ?> + <?= $this->form->number('priority_end', $values, $errors) ?> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + </div> +</form> + +<p class="alert alert-info"><?= t('If you put zero to the low and high priority, this feature will be disabled.') ?></p> diff --git a/app/Template/task/details.php b/app/Template/task/details.php index 74799b15..d885ca9c 100644 --- a/app/Template/task/details.php +++ b/app/Template/task/details.php @@ -4,6 +4,9 @@ <span class="task-score"><?= $this->e($task['score']) ?></span> <?php endif ?> <ul> + <li> + <strong><?= t('Priority: %d', $task['priority']) ?></strong> + </li> <?php if ($task['reference']): ?> <li> <strong><?= t('Reference: %s', $task['reference']) ?></strong> diff --git a/app/Template/task_creation/form.php b/app/Template/task_creation/form.php index c9f367a0..eaf9024d 100644 --- a/app/Template/task_creation/form.php +++ b/app/Template/task_creation/form.php @@ -16,7 +16,7 @@ <div class="form-column"> <?= $this->form->label(t('Title'), 'title') ?> - <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?><br/> + <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?> <?= $this->form->label(t('Description'), 'description') ?> @@ -57,32 +57,34 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Assignee'), 'owner_id') ?> - <?= $this->form->select('owner_id', $users_list, $values, $errors, array('tabindex="3"')) ?><br/> + <?= $this->form->select('owner_id', $users_list, $values, $errors, array('tabindex="3"')) ?> <?= $this->form->label(t('Category'), 'category_id') ?> - <?= $this->form->select('category_id', $categories_list, $values, $errors, array('tabindex="4"')) ?><br/> + <?= $this->form->select('category_id', $categories_list, $values, $errors, array('tabindex="4"')) ?> <?php if (! (count($swimlanes_list) === 1 && key($swimlanes_list) === 0)): ?> <?= $this->form->label(t('Swimlane'), 'swimlane_id') ?> - <?= $this->form->select('swimlane_id', $swimlanes_list, $values, $errors, array('tabindex="5"')) ?><br/> + <?= $this->form->select('swimlane_id', $swimlanes_list, $values, $errors, array('tabindex="5"')) ?> <?php endif ?> <?= $this->form->label(t('Column'), 'column_id') ?> - <?= $this->form->select('column_id', $columns_list, $values, $errors, array('tabindex="6"')) ?><br/> + <?= $this->form->select('column_id', $columns_list, $values, $errors, array('tabindex="6"')) ?> + + <?= $this->task->selectPriority($project, $values) ?> <?= $this->form->label(t('Complexity'), 'score') ?> - <?= $this->form->number('score', $values, $errors, array('tabindex="8"')) ?><br/> + <?= $this->form->number('score', $values, $errors, array('tabindex="9"')) ?> <?= $this->form->label(t('Original estimate'), 'time_estimated') ?> - <?= $this->form->numeric('time_estimated', $values, $errors, array('tabindex="9"')) ?> <?= t('hours') ?><br/> + <?= $this->form->numeric('time_estimated', $values, $errors, array('tabindex="10"')) ?> <?= t('hours') ?> <?= $this->form->label(t('Due Date'), 'date_due') ?> - <?= $this->form->text('date_due', $values, $errors, array('placeholder="'.$this->text->in($date_format, $date_formats).'"', 'tabindex="10"'), 'form-date') ?><br/> + <?= $this->form->text('date_due', $values, $errors, array('placeholder="'.$this->text->in($date_format, $date_formats).'"', 'tabindex="11"'), 'form-date') ?> <div class="form-help"><?= t('Others formats accepted: %s and %s', date('Y-m-d'), date('Y_m_d')) ?></div> </div> <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue" tabindex="11"/> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue" tabindex="12"/> <?= t('or') ?> <?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $values['project_id']), false, 'close-popover') ?> </div> </form>
\ No newline at end of file diff --git a/app/Template/task_modification/edit_task.php b/app/Template/task_modification/edit_task.php index 6fdb77b5..2701dd8f 100644 --- a/app/Template/task_modification/edit_task.php +++ b/app/Template/task_modification/edit_task.php @@ -8,7 +8,7 @@ <div class="form-column"> <?= $this->form->label(t('Title'), 'title') ?> - <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"')) ?><br/> + <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"')) ?> <?= $this->form->label(t('Description'), 'description') ?> <div class="form-tabs"> @@ -45,16 +45,18 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Assignee'), 'owner_id') ?> - <?= $this->form->select('owner_id', $users_list, $values, $errors, array('tabindex="3"')) ?><br/> + <?= $this->form->select('owner_id', $users_list, $values, $errors, array('tabindex="3"')) ?> <?= $this->form->label(t('Category'), 'category_id') ?> - <?= $this->form->select('category_id', $categories_list, $values, $errors, array('tabindex="4"')) ?><br/> + <?= $this->form->select('category_id', $categories_list, $values, $errors, array('tabindex="4"')) ?> <?= $this->form->label(t('Complexity'), 'score') ?> - <?= $this->form->number('score', $values, $errors, array('tabindex="6"')) ?><br/> + <?= $this->form->number('score', $values, $errors, array('tabindex="6"')) ?> + + <?= $this->task->selectPriority($project, $values) ?> <?= $this->form->label(t('Due Date'), 'date_due') ?> - <?= $this->form->text('date_due', $values, $errors, array('placeholder="'.$this->text->in($date_format, $date_formats).'"', 'tabindex="7"'), 'form-date') ?><br/> + <?= $this->form->text('date_due', $values, $errors, array('placeholder="'.$this->text->in($date_format, $date_formats).'"', 'tabindex="8"'), 'form-date') ?> <div class="form-help"><?= t('Others formats accepted: %s and %s', date('Y-m-d'), date('Y_m_d')) ?></div> </div> diff --git a/app/Validator/ProjectValidator.php b/app/Validator/ProjectValidator.php index 53cb7a37..1c6c90f8 100644 --- a/app/Validator/ProjectValidator.php +++ b/app/Validator/ProjectValidator.php @@ -24,6 +24,9 @@ class ProjectValidator extends Base { return array( new Validators\Integer('id', t('This value must be an integer')), + new Validators\Integer('priority_default', t('This value must be an integer')), + new Validators\Integer('priority_start', t('This value must be an integer')), + new Validators\Integer('priority_end', t('This value must be an integer')), new Validators\Integer('is_active', t('This value must be an integer')), new Validators\Required('name', t('The project name is required')), new Validators\MaxLength('name', t('The maximum length is %d characters', 50), 50), diff --git a/app/Validator/TaskValidator.php b/app/Validator/TaskValidator.php index c18a9761..7b73aeba 100644 --- a/app/Validator/TaskValidator.php +++ b/app/Validator/TaskValidator.php @@ -37,6 +37,7 @@ class TaskValidator extends Base new Validators\Integer('recurrence_basedate', t('This value must be an integer')), new Validators\Integer('recurrence_trigger', t('This value must be an integer')), new Validators\Integer('recurrence_status', t('This value must be an integer')), + new Validators\Integer('priority', t('This value must be an integer')), new Validators\MaxLength('title', t('The maximum length is %d characters', 200), 200), new Validators\MaxLength('reference', t('The maximum length is %d characters', 50), 50), new Validators\Date('date_due', t('Invalid date'), $this->dateParser->getDateFormats()), diff --git a/tests/units/Helper/TaskHelperTest.php b/tests/units/Helper/TaskHelperTest.php new file mode 100644 index 00000000..726188e4 --- /dev/null +++ b/tests/units/Helper/TaskHelperTest.php @@ -0,0 +1,32 @@ +<?php + +require_once __DIR__.'/../Base.php'; + +use Kanboard\Helper\Task; + +class TaskHelperTest extends Base +{ + public function testSelectPriority() + { + $helper = new Task($this->container); + $this->assertNotEmpty($helper->selectPriority(array('priority_end' => '3', 'priority_start' => '1', 'priority_default' => '2'), array())); + $this->assertEmpty($helper->selectPriority(array('priority_end' => '3', 'priority_start' => '3', 'priority_default' => '2'), array())); + } + + public function testFormatPriority() + { + $helper = new Task($this->container); + + $this->assertEquals( + '<span class="task-board-priority" title="Task priority">P2</span>', + $helper->formatPriority(array('priority_end' => '3', 'priority_start' => '1', 'priority_default' => '2'), array('priority' => 2)) + ); + + $this->assertEquals( + '<span class="task-board-priority" title="Task priority">-P6</span>', + $helper->formatPriority(array('priority_end' => '3', 'priority_start' => '1', 'priority_default' => '2'), array('priority' => -6)) + ); + + $this->assertEmpty($helper->formatPriority(array('priority_end' => '3', 'priority_start' => '3', 'priority_default' => '2'), array())); + } +} diff --git a/tests/units/Model/ProjectTest.php b/tests/units/Model/ProjectTest.php index afd047b0..cadb42a6 100644 --- a/tests/units/Model/ProjectTest.php +++ b/tests/units/Model/ProjectTest.php @@ -305,4 +305,24 @@ class ProjectTest extends Base $this->assertEquals('', $project['owner_username']); $this->assertEquals(0, $project['owner_id']); } + + public function testPriority() + { + $projectModel = new Project($this->container); + $this->assertEquals(1, $projectModel->create(array('name' => 'My project 2'))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(0, $project['priority_default']); + $this->assertEquals(0, $project['priority_start']); + $this->assertEquals(3, $project['priority_end']); + + $this->assertTrue($projectModel->update(array('id' => 1, 'priority_start' => 2, 'priority_end' => 5, 'priority_default' => 4))); + + $project = $projectModel->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals(4, $project['priority_default']); + $this->assertEquals(2, $project['priority_start']); + $this->assertEquals(5, $project['priority_end']); + } } |