diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/Controller/Base.php | 1 | ||||
-rw-r--r-- | app/Controller/Subtask.php | 185 | ||||
-rw-r--r-- | app/Controller/Task.php | 1 | ||||
-rw-r--r-- | app/Locales/de_DE/translations.php | 25 | ||||
-rw-r--r-- | app/Locales/es_ES/translations.php | 25 | ||||
-rw-r--r-- | app/Locales/fr_FR/translations.php | 25 | ||||
-rw-r--r-- | app/Locales/pl_PL/translations.php | 25 | ||||
-rw-r--r-- | app/Locales/pt_BR/translations.php | 25 | ||||
-rw-r--r-- | app/Model/Base.php | 1 | ||||
-rw-r--r-- | app/Model/SubTask.php | 179 | ||||
-rw-r--r-- | app/Schema/Mysql.php | 19 | ||||
-rw-r--r-- | app/Schema/Sqlite.php | 18 | ||||
-rw-r--r-- | app/Templates/comment_remove.php | 2 | ||||
-rw-r--r-- | app/Templates/file_show.php | 17 | ||||
-rw-r--r-- | app/Templates/subtask_create.php | 25 | ||||
-rw-r--r-- | app/Templates/subtask_edit.php | 30 | ||||
-rw-r--r-- | app/Templates/subtask_remove.php | 16 | ||||
-rw-r--r-- | app/Templates/subtask_show.php | 60 | ||||
-rw-r--r-- | app/Templates/task_show.php | 23 | ||||
-rw-r--r-- | app/Templates/task_sidebar.php | 1 | ||||
-rw-r--r-- | app/helpers.php | 5 |
21 files changed, 689 insertions, 19 deletions
diff --git a/app/Controller/Base.php b/app/Controller/Base.php index b21d9b8f..5829fc36 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -23,6 +23,7 @@ use Model\LastLogin; * @property \Model\Ldap $ldap * @property \Model\Project $project * @property \Model\RememberMe $rememberMe + * @property \Model\SubTask $subTask * @property \Model\Task $task * @property \Model\User $user */ diff --git a/app/Controller/Subtask.php b/app/Controller/Subtask.php new file mode 100644 index 00000000..5ef193c8 --- /dev/null +++ b/app/Controller/Subtask.php @@ -0,0 +1,185 @@ +<?php + +namespace Controller; + +/** + * SubTask controller + * + * @package controller + * @author Frederic Guillot + */ +class Subtask extends Base +{ + /** + * Get the current subtask + * + * @access private + * @return array + */ + private function getSubtask() + { + $subtask = $this->subTask->getById($this->request->getIntegerParam('subtask_id')); + + if (! $subtask) { + $this->notfound(); + } + + return $subtask; + } + + /** + * Creation form + * + * @access public + */ + public function create() + { + $task = $this->getTask(); + + $this->response->html($this->taskLayout('subtask_create', array( + 'values' => array( + 'task_id' => $task['id'], + ), + 'errors' => array(), + 'users_list' => $this->project->getUsersList($task['project_id']), + 'task' => $task, + 'menu' => 'tasks', + 'title' => t('Add a sub-task') + ))); + } + + /** + * Validation and creation + * + * @access public + */ + public function save() + { + $task = $this->getTask(); + $values = $this->request->getValues(); + + list($valid, $errors) = $this->subTask->validate($values); + + if ($valid) { + + if ($this->subTask->create($values)) { + $this->session->flash(t('Sub-task added successfully.')); + } + else { + $this->session->flashError(t('Unable to create your sub-task.')); + } + + if (isset($values['another_subtask']) && $values['another_subtask'] == 1) { + $this->response->redirect('?controller=subtask&action=create&task_id='.$task['id']); + } + + $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'#subtasks'); + } + + $this->response->html($this->taskLayout('subtask_create', array( + 'values' => $values, + 'errors' => $errors, + 'users_list' => $this->project->getUsersList($task['project_id']), + 'task' => $task, + 'menu' => 'tasks', + 'title' => t('Add a sub-task') + ))); + } + + /** + * Edit form + * + * @access public + */ + public function edit() + { + $task = $this->getTask(); + $subtask = $this->getSubTask(); + + $this->response->html($this->taskLayout('subtask_edit', array( + 'values' => $subtask, + 'errors' => array(), + 'users_list' => $this->project->getUsersList($task['project_id']), + 'status_list' => $this->subTask->getStatusList(), + 'subtask' => $subtask, + 'task' => $task, + 'menu' => 'tasks', + 'title' => t('Edit a sub-task') + ))); + } + + /** + * Update and validate a subtask + * + * @access public + */ + public function update() + { + $task = $this->getTask(); + $subtask = $this->getSubtask(); + + $values = $this->request->getValues(); + list($valid, $errors) = $this->subTask->validate($values); + + if ($valid) { + + if ($this->subTask->update($values)) { + $this->session->flash(t('Sub-task updated successfully.')); + } + else { + $this->session->flashError(t('Unable to update your sub-task.')); + } + + $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'#subtasks'); + } + + $this->response->html($this->taskLayout('subtask_edit', array( + 'values' => $values, + 'errors' => $errors, + 'users_list' => $this->project->getUsersList($task['project_id']), + 'status_list' => $this->subTask->getStatusList(), + 'subtask' => $subtask, + 'task' => $task, + 'menu' => 'tasks', + 'title' => t('Edit a sub-task') + ))); + } + + /** + * Confirmation dialog before removing a subtask + * + * @access public + */ + public function confirm() + { + $task = $this->getTask(); + $subtask = $this->getSubtask(); + + $this->response->html($this->taskLayout('subtask_remove', array( + 'subtask' => $subtask, + 'task' => $task, + 'menu' => 'tasks', + 'title' => t('Remove a sub-task') + ))); + } + + /** + * Remove a subtask + * + * @access public + */ + public function remove() + { + $task = $this->getTask(); + $subtask = $this->getSubtask(); + + if ($this->subTask->remove($subtask['id'])) { + $this->session->flash(t('Sub-task removed successfully.')); + } + else { + $this->session->flashError(t('Unable to remove this sub-task.')); + } + + $this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'#subtasks'); + } +} diff --git a/app/Controller/Task.php b/app/Controller/Task.php index 8230eef3..68e3728a 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -62,6 +62,7 @@ class Task extends Base $this->response->html($this->taskLayout('task_show', array( 'files' => $this->file->getAll($task['id']), 'comments' => $this->comment->getAll($task['id']), + 'subtasks' => $this->subTask->getAll($task['id']), 'task' => $task, 'columns_list' => $this->board->getColumnsList($task['project_id']), 'colors_list' => $this->task->getColors(), diff --git a/app/Locales/de_DE/translations.php b/app/Locales/de_DE/translations.php index 90958853..b554b01d 100644 --- a/app/Locales/de_DE/translations.php +++ b/app/Locales/de_DE/translations.php @@ -346,4 +346,29 @@ return array( // 'Add a comment' => '', // 'Edit a comment' => '', // 'Summary' => '', + // 'Time tracking' => '', + // 'Estimate:' => '', + // 'Spent:' => '', + // 'Do you really want to remove this sub-task?' => '', + // 'Remaining:' => '', + // 'hours' => '', + // 'spent' => '', + // 'estimated' => '', + // 'Sub-Tasks' => '', + // 'Add a sub-task' => '', + // 'Original Estimate' => '', + // 'Create another sub-task' => '', + // 'Time Spent' => '', + // 'Edit a sub-task' => '', + // 'Remove a sub-task' => '', + // 'The time must be a numeric value' => '', + // 'Todo' => '', + // 'In progress' => '', + // 'Done' => '', + // 'Sub-task removed successfully.' => '', + // 'Unable to remove this sub-task.' => '', + // 'Sub-task updated successfully.' => '', + // 'Unable to update your sub-task.' => '', + // 'Unable to create your sub-task.' => '', + // 'Sub-task added successfully.' => '', ); diff --git a/app/Locales/es_ES/translations.php b/app/Locales/es_ES/translations.php index d0d9efa8..0d8384dd 100644 --- a/app/Locales/es_ES/translations.php +++ b/app/Locales/es_ES/translations.php @@ -344,4 +344,29 @@ return array( // 'Add a comment' => '', // 'Edit a comment' => '', // 'Summary' => '', + // 'Time tracking' => '', + // 'Estimate:' => '', + // 'Spent:' => '', + // 'Do you really want to remove this sub-task?' => '', + // 'Remaining:' => '', + // 'hours' => '', + // 'spent' => '', + // 'estimated' => '', + // 'Sub-Tasks' => '', + // 'Add a sub-task' => '', + // 'Original Estimate' => '', + // 'Create another sub-task' => '', + // 'Time Spent' => '', + // 'Edit a sub-task' => '', + // 'Remove a sub-task' => '', + // 'The time must be a numeric value' => '', + // 'Todo' => '', + // 'In progress' => '', + // 'Done' => '', + // 'Sub-task removed successfully.' => '', + // 'Unable to remove this sub-task.' => '', + // 'Sub-task updated successfully.' => '', + // 'Unable to update your sub-task.' => '', + // 'Unable to create your sub-task.' => '', + // 'Sub-task added successfully.' => '', ); diff --git a/app/Locales/fr_FR/translations.php b/app/Locales/fr_FR/translations.php index d1ed9f91..56acbed5 100644 --- a/app/Locales/fr_FR/translations.php +++ b/app/Locales/fr_FR/translations.php @@ -344,4 +344,29 @@ return array( 'Add a comment' => 'Ajouter un commentaire', 'Edit a comment' => 'Modifier un commentaire', 'Summary' => 'Résumé', + 'Time tracking' => 'Gestion du temps', + 'Estimate:' => 'Estimation :', + 'Spent:' => 'Passé :', + 'Do you really want to remove this sub-task?' => 'Voulez-vous vraiment supprimer cette sous-tâche ?', + 'Remaining:' => 'Restant :', + 'hours' => 'heures', + 'spent' => 'passé', + 'estimated' => 'estimé', + 'Sub-Tasks' => 'Sous-Tâches', + 'Add a sub-task' => 'Ajouter une sous-tâche', + 'Original Estimate' => 'Estimation originale', + 'Create another sub-task' => 'Créer une autre sous-tâche', + 'Time Spent' => 'Temps passé', + 'Edit a sub-task' => 'Modifier une sous-tâche', + 'Remove a sub-task' => 'Supprimer une sous-tâche', + 'The time must be a numeric value' => 'Le temps doit-être une valeur numérique', + 'Todo' => 'À faire', + 'In progress' => 'En cours', + 'Done' => 'Terminé', + 'Sub-task removed successfully.' => 'Sous-tâche supprimée avec succès.', + 'Unable to remove this sub-task.' => 'Impossible de supprimer cette sous-tâche.', + 'Sub-task updated successfully.' => 'Sous-tâche mise à jour avec succès.', + 'Unable to update your sub-task.' => 'Impossible de mettre à jour votre sous-tâche.', + 'Unable to create your sub-task.' => 'Impossible de créer votre sous-tâche.', + 'Sub-task added successfully.' => 'Sous-tâche ajouté avec succès.', ); diff --git a/app/Locales/pl_PL/translations.php b/app/Locales/pl_PL/translations.php index 3490810a..dca01a2c 100644 --- a/app/Locales/pl_PL/translations.php +++ b/app/Locales/pl_PL/translations.php @@ -349,4 +349,29 @@ return array( // 'Add a comment' => '', // 'Edit a comment' => '', // 'Summary' => '', + // 'Time tracking' => '', + // 'Estimate:' => '', + // 'Spent:' => '', + // 'Do you really want to remove this sub-task?' => '', + // 'Remaining:' => '', + // 'hours' => '', + // 'spent' => '', + // 'estimated' => '', + // 'Sub-Tasks' => '', + // 'Add a sub-task' => '', + // 'Original Estimate' => '', + // 'Create another sub-task' => '', + // 'Time Spent' => '', + // 'Edit a sub-task' => '', + // 'Remove a sub-task' => '', + // 'The time must be a numeric value' => '', + // 'Todo' => '', + // 'In progress' => '', + // 'Done' => '', + // 'Sub-task removed successfully.' => '', + // 'Unable to remove this sub-task.' => '', + // 'Sub-task updated successfully.' => '', + // 'Unable to update your sub-task.' => '', + // 'Unable to create your sub-task.' => '', + // 'Sub-task added successfully.' => '', ); diff --git a/app/Locales/pt_BR/translations.php b/app/Locales/pt_BR/translations.php index 267006ce..00fcccef 100644 --- a/app/Locales/pt_BR/translations.php +++ b/app/Locales/pt_BR/translations.php @@ -345,4 +345,29 @@ return array( // 'Add a comment' => '', // 'Edit a comment' => '', // 'Summary' => '', + // 'Time tracking' => '', + // 'Estimate:' => '', + // 'Spent:' => '', + // 'Do you really want to remove this sub-task?' => '', + // 'Remaining:' => '', + // 'hours' => '', + // 'spent' => '', + // 'estimated' => '', + // 'Sub-Tasks' => '', + // 'Add a sub-task' => '', + // 'Original Estimate' => '', + // 'Create another sub-task' => '', + // 'Time Spent' => '', + // 'Edit a sub-task' => '', + // 'Remove a sub-task' => '', + // 'The time must be a numeric value' => '', + // 'Todo' => '', + // 'In progress' => '', + // 'Done' => '', + // 'Sub-task removed successfully.' => '', + // 'Unable to remove this sub-task.' => '', + // 'Sub-task updated successfully.' => '', + // 'Unable to update your sub-task.' => '', + // 'Unable to create your sub-task.' => '', + // 'Sub-task added successfully.' => '', ); diff --git a/app/Model/Base.php b/app/Model/Base.php index e95296bb..ddc06c3d 100644 --- a/app/Model/Base.php +++ b/app/Model/Base.php @@ -14,6 +14,7 @@ require __DIR__.'/../../vendor/SimpleValidator/Validators/AlphaNumeric.php'; require __DIR__.'/../../vendor/SimpleValidator/Validators/GreaterThan.php'; require __DIR__.'/../../vendor/SimpleValidator/Validators/Date.php'; require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php'; +require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php'; use Core\Event; use PicoDb\Database; diff --git a/app/Model/SubTask.php b/app/Model/SubTask.php new file mode 100644 index 00000000..21ccdaac --- /dev/null +++ b/app/Model/SubTask.php @@ -0,0 +1,179 @@ +<?php + +namespace Model; + +use SimpleValidator\Validator; +use SimpleValidator\Validators; + +/** + * Subtask model + * + * @package model + * @author Frederic Guillot + */ +class SubTask extends Base +{ + /** + * SQL table name + * + * @var string + */ + const TABLE = 'task_has_subtasks'; + + /** + * Task "done" status + * + * @var integer + */ + const STATUS_DONE = 2; + + /** + * Task "in progress" status + * + * @var integer + */ + const STATUS_INPROGRESS = 1; + + /** + * Task "todo" status + * + * @var integer + */ + const STATUS_TODO = 0; + + /** + * Get available status + * + * @access public + * @return array + */ + public function getStatusList() + { + $status = array( + self::STATUS_TODO => t('Todo'), + self::STATUS_INPROGRESS => t('In progress'), + self::STATUS_DONE => t('Done'), + ); + + asort($status); + + return $status; + } + + /** + * Get all subtasks for a given task + * + * @access public + * @param integer $task_id Task id + * @return array + */ + public function getAll($task_id) + { + $status = $this->getStatusList(); + $subtasks = $this->db->table(self::TABLE) + ->eq('task_id', $task_id) + ->columns(self::TABLE.'.*', User::TABLE.'.username') + ->join(User::TABLE, 'id', 'user_id') + ->findAll(); + + foreach ($subtasks as &$subtask) { + $subtask['status_name'] = $status[$subtask['status']]; + } + + return $subtasks; + } + + /** + * Get a subtask by the id + * + * @access public + * @param integer $subtask_id Subtask id + * @return array + */ + public function getById($subtask_id) + { + return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne(); + } + + /** + * Create + * + * @access public + * @param array $values Form values + * @return bool + */ + public function create(array $values) + { + if (isset($values['another_subtask'])) { + unset($values['another_subtask']); + } + + if (isset($values['time_estimated']) && empty($values['time_estimated'])) { + $values['time_estimated'] = 0; + } + + if (isset($values['time_spent']) && empty($values['time_spent'])) { + $values['time_spent'] = 0; + } + + return $this->db->table(self::TABLE)->save($values); + } + + /** + * Update + * + * @access public + * @param array $values Form values + * @return bool + */ + public function update(array $values) + { + if (isset($values['time_estimated']) && empty($values['time_estimated'])) { + $values['time_estimated'] = 0; + } + + if (isset($values['time_spent']) && empty($values['time_spent'])) { + $values['time_spent'] = 0; + } + + return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); + } + + /** + * Remove + * + * @access public + * @param integer $subtask_id Subtask id + * @return bool + */ + public function remove($subtask_id) + { + return $this->db->table(self::TABLE)->eq('id', $subtask_id)->remove(); + } + + /** + * Validate creation/modification + * + * @access public + * @param array $values Form values + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validate(array $values) + { + $v = new Validator($values, array( + new Validators\Required('task_id', t('The task id is required')), + new Validators\Integer('task_id', t('The task id must be an integer')), + new Validators\Required('title', t('The title is required')), + new Validators\MaxLength('title', t('The maximum length is %d characters', 100), 100), + new Validators\Integer('user_id', t('The user id must be an integer')), + new Validators\Integer('status', t('The status must be an integer')), + new Validators\Numeric('time_estimated', t('The time must be a numeric value')), + new Validators\Numeric('time_spent', t('The time must be a numeric value')), + )); + + return array( + $v->execute(), + $v->getErrors() + ); + } +} diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index d3b111f9..3df38dee 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -2,7 +2,24 @@ namespace Schema; -const VERSION = 17; +const VERSION = 18; + +function version_18($pdo) +{ + $pdo->exec(" + CREATE TABLE task_has_subtasks ( + id INT NOT NULL AUTO_INCREMENT, + title VARCHAR(255), + status INT DEFAULT 0, + time_estimated INT DEFAULT 0, + time_spent INT DEFAULT 0, + task_id INT, + user_id INT, + PRIMARY KEY (id), + FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE + ) ENGINE=InnoDB CHARSET=utf8" + ); +} function version_17($pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 94ef0316..663c7d34 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -2,7 +2,23 @@ namespace Schema; -const VERSION = 17; +const VERSION = 18; + +function version_18($pdo) +{ + $pdo->exec(" + CREATE TABLE task_has_subtasks ( + id INTEGER PRIMARY KEY, + title TEXT COLLATE NOCASE, + status INTEGER DEFAULT 0, + time_estimated INTEGER DEFAULT 0, + time_spent INTEGER DEFAULT 0, + task_id INTEGER, + user_id INTEGER, + FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE + )" + ); +} function version_17($pdo) { diff --git a/app/Templates/comment_remove.php b/app/Templates/comment_remove.php index 02a23f93..6409d7c0 100644 --- a/app/Templates/comment_remove.php +++ b/app/Templates/comment_remove.php @@ -1,5 +1,5 @@ <div class="page-header"> - <h2><?= t('Add a comment') ?></h2> + <h2><?= t('Remove a comment') ?></h2> </div> <div class="confirm"> diff --git a/app/Templates/file_show.php b/app/Templates/file_show.php new file mode 100644 index 00000000..674861dd --- /dev/null +++ b/app/Templates/file_show.php @@ -0,0 +1,17 @@ +<div class="page-header"> + <h2><?= t('Attachments') ?></h2> +</div> + +<ul class="task-show-files"> +<?php foreach ($files as $file): ?> + <li> + <a href="?controller=file&action=download&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>"><?= Helper\escape($file['name']) ?></a> + <span class="task-show-file-actions"> + <?php if ($file['is_image']): ?> + <a href="?controller=file&action=open&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>" class="popover"><?= t('open') ?></a>, + <?php endif ?> + <a href="?controller=file&action=confirm&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>"><?= t('remove') ?></a> + </span> + </li> +<?php endforeach ?> +</ul>
\ No newline at end of file diff --git a/app/Templates/subtask_create.php b/app/Templates/subtask_create.php new file mode 100644 index 00000000..a456aa37 --- /dev/null +++ b/app/Templates/subtask_create.php @@ -0,0 +1,25 @@ +<div class="page-header"> + <h2><?= t('Add a sub-task') ?></h2> +</div> + +<form method="post" action="?controller=subtask&action=save&task_id=<?= $task['id'] ?>" autocomplete="off"> + + <?= Helper\form_hidden('task_id', $values) ?> + + <?= Helper\form_label(t('Title'), 'title') ?> + <?= Helper\form_text('title', $values, $errors, array('required autofocus')) ?><br/> + + <?= Helper\form_label(t('Assignee'), 'user_id') ?> + <?= Helper\form_select('user_id', $users_list, $values, $errors) ?><br/> + + <?= Helper\form_label(t('Original Estimate'), 'time_estimated') ?> + <?= Helper\form_numeric('time_estimated', $values, $errors) ?> <?= t('hours') ?><br/> + + <?= Helper\form_checkbox('another_subtask', t('Create another sub-task'), 1, isset($values['another_subtask']) && $values['another_subtask'] == 1) ?> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + <?= t('or') ?> + <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>"><?= t('cancel') ?></a> + </div> +</form> diff --git a/app/Templates/subtask_edit.php b/app/Templates/subtask_edit.php new file mode 100644 index 00000000..3080cdad --- /dev/null +++ b/app/Templates/subtask_edit.php @@ -0,0 +1,30 @@ +<div class="page-header"> + <h2><?= t('Edit a sub-task') ?></h2> +</div> + +<form method="post" action="?controller=subtask&action=update&task_id=<?= $task['id'] ?>&subtask_id=<?= $subtask['id'] ?>" autocomplete="off"> + + <?= Helper\form_hidden('id', $values) ?> + <?= Helper\form_hidden('task_id', $values) ?> + + <?= Helper\form_label(t('Title'), 'title') ?> + <?= Helper\form_text('title', $values, $errors, array('required autofocus')) ?><br/> + + <?= Helper\form_label(t('Status'), 'status') ?> + <?= Helper\form_select('status', $status_list, $values, $errors) ?><br/> + + <?= Helper\form_label(t('Assignee'), 'user_id') ?> + <?= Helper\form_select('user_id', $users_list, $values, $errors) ?><br/> + + <?= Helper\form_label(t('Original Estimate'), 'time_estimated') ?> + <?= Helper\form_numeric('time_estimated', $values, $errors) ?> <?= t('hours') ?><br/> + + <?= Helper\form_label(t('Time Spent'), 'time_spent') ?> + <?= Helper\form_numeric('time_spent', $values, $errors) ?> <?= t('hours') ?><br/> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + <?= t('or') ?> + <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>"><?= t('cancel') ?></a> + </div> +</form> diff --git a/app/Templates/subtask_remove.php b/app/Templates/subtask_remove.php new file mode 100644 index 00000000..2862176c --- /dev/null +++ b/app/Templates/subtask_remove.php @@ -0,0 +1,16 @@ +<div class="page-header"> + <h2><?= t('Remove a sub-task') ?></h2> +</div> + +<div class="confirm"> + <p class="alert alert-info"> + <?= t('Do you really want to remove this sub-task?') ?> + </p> + + <p><strong><?= Helper\escape($subtask['title']) ?></strong></p> + + <div class="form-actions"> + <a href="?controller=subtask&action=remove&task_id=<?= $task['id'] ?>&subtask_id=<?= $subtask['id'] ?>" class="btn btn-red"><?= t('Yes') ?></a> + <?= t('or') ?> <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>#subtasks"><?= t('cancel') ?></a> + </div> +</div>
\ No newline at end of file diff --git a/app/Templates/subtask_show.php b/app/Templates/subtask_show.php new file mode 100644 index 00000000..b9385c7e --- /dev/null +++ b/app/Templates/subtask_show.php @@ -0,0 +1,60 @@ +<div class="page-header"> + <h2><?= t('Sub-Tasks') ?></h2> +</div> + +<?php + +$total_spent = 0; +$total_estimated = 0; +$total_remaining = 0; + +?> + +<table class="subtasks-table"> + <tr> + <th width="40%"><?= t('Title') ?></th> + <th><?= t('Status') ?></th> + <th><?= t('Assignee') ?></th> + <th><?= t('Time tracking') ?></th> + <th><?= t('Actions') ?></th> + </tr> + <?php foreach ($subtasks as $subtask): ?> + <tr> + <td><?= Helper\escape($subtask['title']) ?></td> + <td><?= Helper\escape($subtask['status_name']) ?></td> + <td> + <?php if (! empty($subtask['username'])): ?> + <?= Helper\escape($subtask['username']) ?> + <?php endif ?> + </td> + <td> + <?php if (! empty($subtask['time_spent'])): ?> + <strong><?= Helper\escape($subtask['time_spent']).'h' ?></strong> <?= t('spent') ?> + <?php endif ?> + + <?php if (! empty($subtask['time_estimated'])): ?> + <strong><?= Helper\escape($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?> + <?php endif ?> + </td> + <td> + <a href="?controller=subtask&action=edit&task_id=<?= $task['id'] ?>&subtask_id=<?= $subtask['id'] ?>"><?= t('Edit') ?></a> + <?= t('or') ?> + <a href="?controller=subtask&action=confirm&task_id=<?= $task['id'] ?>&subtask_id=<?= $subtask['id'] ?>"><?= t('Remove') ?></a> + </td> + </tr> + <?php + $total_estimated += $subtask['time_estimated']; + $total_spent += $subtask['time_spent']; + $total_remaining = $total_estimated - $total_spent; + ?> + <?php endforeach ?> +</table> + +<div class="subtasks-time-tracking"> + <h4><?= t('Time tracking') ?></h4> + <ul> + <li><?= t('Estimate:') ?> <strong><?= Helper\escape($total_estimated) ?></strong> <?= t('hours') ?></li> + <li><?= t('Spent:') ?> <strong><?= Helper\escape($total_spent) ?></strong> <?= t('hours') ?></li> + <li><?= t('Remaining:') ?> <strong><?= Helper\escape($total_remaining > 0 ? $total_remaining : 0) ?></strong> <?= t('hours') ?></li> + </ul> +</div>
\ No newline at end of file diff --git a/app/Templates/task_show.php b/app/Templates/task_show.php index 53cdbae8..4c3d4697 100644 --- a/app/Templates/task_show.php +++ b/app/Templates/task_show.php @@ -62,23 +62,14 @@ <?php if (! empty($files)): ?> <div id="attachments" class="task-show-section"> - <div class="page-header"> - <h2><?= t('Attachments') ?></h2> - </div> + <?= Helper\template('file_show', array('task' => $task, 'files' => $files)) ?> +</div> +<?php endif ?> - <ul class="task-show-files"> - <?php foreach ($files as $file): ?> - <li> - <a href="?controller=file&action=download&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>"><?= Helper\escape($file['name']) ?></a> - <span class="task-show-file-actions"> - <?php if ($file['is_image']): ?> - <a href="?controller=file&action=open&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>" class="popover"><?= t('open') ?></a>, - <?php endif ?> - <a href="?controller=file&action=confirm&file_id=<?= $file['id'] ?>&task_id=<?= $task['id'] ?>"><?= t('remove') ?></a> - </span> - </li> - <?php endforeach ?> - </ul> + +<?php if (! empty($subtasks)): ?> +<div id="subtasks" class="task-show-section"> + <?= Helper\template('subtask_show', array('task' => $task, 'subtasks' => $subtasks)) ?> </div> <?php endif ?> diff --git a/app/Templates/task_sidebar.php b/app/Templates/task_sidebar.php index 8a3939b8..d97c44e2 100644 --- a/app/Templates/task_sidebar.php +++ b/app/Templates/task_sidebar.php @@ -5,6 +5,7 @@ <li><a href="?controller=task&action=show&task_id=<?= $task['id'] ?>"><?= t('Summary') ?></a></li> <li><a href="?controller=task&action=edit&task_id=<?= $task['id'] ?>"><?= t('Edit the task') ?></a></li> <li><a href="?controller=task&action=editDescription&task_id=<?= $task['id'] ?>"><?= t('Edit the description') ?></a></li> + <li><a href="?controller=subtask&action=create&task_id=<?= $task['id'] ?>"><?= t('Add a sub-task') ?></a></li> <li><a href="?controller=comment&action=create&task_id=<?= $task['id'] ?>"><?= t('Add a comment') ?></a></li> <li><a href="?controller=file&action=create&task_id=<?= $task['id'] ?>"><?= t('Attach a document') ?></a></li> <li><a href="?controller=task&action=duplicate&project_id=<?= $task['project_id'] ?>&task_id=<?= $task['id'] ?>"><?= t('Duplicate') ?></a></li> diff --git a/app/helpers.php b/app/helpers.php index 8351328a..2dcb38e8 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -260,3 +260,8 @@ function form_number($name, $values = array(), array $errors = array(), array $a { return form_input('number', $name, $values, $errors, $attributes, $class); } + +function form_numeric($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '') +{ + return form_input('text', $name, $values, $errors, $attributes, $class.' form-numeric'); +} |