diff options
-rw-r--r-- | app/Core/Listener.php | 4 | ||||
-rw-r--r-- | app/Core/Request.php | 69 | ||||
-rw-r--r-- | app/Core/Response.php | 99 | ||||
-rw-r--r-- | app/Core/Router.php | 2 | ||||
-rw-r--r-- | app/Core/Session.php | 39 | ||||
-rw-r--r-- | app/Core/Translator.php | 2 | ||||
-rw-r--r-- | app/Model/Action.php | 2 | ||||
-rw-r--r-- | app/Model/Category.php | 4 | ||||
-rw-r--r-- | app/Model/Config.php | 4 | ||||
-rw-r--r-- | app/Model/File.php | 5 | ||||
-rw-r--r-- | app/Model/Project.php | 6 | ||||
-rw-r--r-- | app/Templates/board_public.php | 49 | ||||
-rw-r--r-- | app/Templates/board_show.php | 53 | ||||
-rw-r--r-- | app/Templates/board_task.php | 76 | ||||
-rw-r--r-- | app/Templates/project_search.php | 64 | ||||
-rw-r--r-- | app/Templates/project_tasks.php | 56 | ||||
-rw-r--r-- | app/Templates/task_table.php | 54 | ||||
-rw-r--r-- | assets/css/app.css | 126 | ||||
-rw-r--r-- | assets/js/board.js | 4 |
19 files changed, 412 insertions, 306 deletions
diff --git a/app/Core/Listener.php b/app/Core/Listener.php index b8bdd680..0df641ba 100644 --- a/app/Core/Listener.php +++ b/app/Core/Listener.php @@ -11,6 +11,10 @@ namespace Core; interface Listener { /** + * Execute the listener + * + * @access public + * @param array $data Event data * @return boolean */ public function execute(array $data); diff --git a/app/Core/Request.php b/app/Core/Request.php index df8ea41a..7e9f24ac 100644 --- a/app/Core/Request.php +++ b/app/Core/Request.php @@ -2,39 +2,92 @@ namespace Core; +/** + * Request class + * + * @package core + * @author Frederic Guillot + */ class Request { + /** + * Get URL string parameter + * + * @access public + * @param string $name Parameter name + * @param string $default_value Default value + * @return string + */ public function getStringParam($name, $default_value = '') { return isset($_GET[$name]) ? $_GET[$name] : $default_value; } + /** + * Get URL integer parameter + * + * @access public + * @param string $name Parameter name + * @param integer $default_value Default value + * @return integer + */ public function getIntegerParam($name, $default_value = 0) { return isset($_GET[$name]) && ctype_digit($_GET[$name]) ? (int) $_GET[$name] : $default_value; } + /** + * Get a form value + * + * @access public + * @param string $name Form field name + * @return string|null + */ public function getValue($name) { $values = $this->getValues(); return isset($values[$name]) ? $values[$name] : null; } + /** + * Get form values or unserialized json request + * + * @access public + * @return array + */ public function getValues() { - if (! empty($_POST)) return $_POST; + if (! empty($_POST)) { + return $_POST; + } $result = json_decode($this->getBody(), true); - if ($result) return $result; + + if ($result) { + return $result; + } return array(); } + /** + * Get the raw body of the HTTP request + * + * @access public + * @return string + */ public function getBody() { return file_get_contents('php://input'); } + /** + * Get the content of an uploaded file + * + * @access public + * @param string $name Form file name + * @return string + */ public function getFileContent($name) { if (isset($_FILES[$name])) { @@ -44,11 +97,23 @@ class Request return ''; } + /** + * Return true if the HTTP request is sent with the POST method + * + * @access public + * @return bool + */ public function isPost() { return isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST'; } + /** + * Return true if the HTTP request is an Ajax request + * + * @access public + * @return bool + */ public function isAjax() { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; diff --git a/app/Core/Response.php b/app/Core/Response.php index ee98c9ed..87d2fa4a 100644 --- a/app/Core/Response.php +++ b/app/Core/Response.php @@ -2,20 +2,41 @@ namespace Core; +/** + * Response class + * + * @package core + * @author Frederic Guillot + */ class Response { + /** + * Send a custom Content-Type header + * + * @access public + * @param string $mimetype Mime-type + */ public function contentType($mimetype) { header('Content-Type: '.$mimetype); } + /** + * Force the browser to download an attachment + * + * @access public + * @param string $filename File name + */ public function forceDownload($filename) { header('Content-Disposition: attachment; filename="'.$filename.'"'); } /** - * @param integer $status_code + * Send a custom HTTP status code + * + * @access public + * @param integer $status_code HTTP status code */ public function status($status_code) { @@ -23,12 +44,25 @@ class Response header($_SERVER['SERVER_PROTOCOL'].' '.$status_code); } + /** + * Redirect to another URL + * + * @access public + * @param string $url Redirection URL + */ public function redirect($url) { header('Location: '.$url); exit; } + /** + * Send a Json response + * + * @access public + * @param array $data Data to serialize in json + * @param integer $status_code HTTP status code + */ public function json(array $data, $status_code = 200) { $this->status($status_code); @@ -39,6 +73,13 @@ class Response exit; } + /** + * Send a text response + * + * @access public + * @param string $data Raw data + * @param integer $status_code HTTP status code + */ public function text($data, $status_code = 200) { $this->status($status_code); @@ -49,6 +90,13 @@ class Response exit; } + /** + * Send a HTML response + * + * @access public + * @param string $data Raw data + * @param integer $status_code HTTP status code + */ public function html($data, $status_code = 200) { $this->status($status_code); @@ -59,6 +107,13 @@ class Response exit; } + /** + * Send a XML response + * + * @access public + * @param string $data Raw data + * @param integer $status_code HTTP status code + */ public function xml($data, $status_code = 200) { $this->status($status_code); @@ -69,6 +124,13 @@ class Response exit; } + /** + * Send a javascript response + * + * @access public + * @param string $data Raw data + * @param integer $status_code HTTP status code + */ public function js($data, $status_code = 200) { $this->status($status_code); @@ -79,6 +141,13 @@ class Response exit; } + /** + * Send a binary response + * + * @access public + * @param string $data Raw data + * @param integer $status_code HTTP status code + */ public function binary($data, $status_code = 200) { $this->status($status_code); @@ -90,6 +159,12 @@ class Response exit; } + /** + * Send the security header: Content-Security-Policy + * + * @access public + * @param array $policies CSP rules + */ public function csp(array $policies = array()) { $policies['default-src'] = "'self'"; @@ -119,16 +194,31 @@ class Response header('Content-Security-Policy: '.$values); } + /** + * Send the security header: X-Content-Type-Options + * + * @access public + */ public function nosniff() { header('X-Content-Type-Options: nosniff'); } + /** + * Send the security header: X-XSS-Protection + * + * @access public + */ public function xss() { header('X-XSS-Protection: 1; mode=block'); } + /** + * Send the security header: Strict-Transport-Security (only if we use HTTPS) + * + * @access public + */ public function hsts() { if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { @@ -136,6 +226,13 @@ class Response } } + /** + * Send the security header: X-Frame-Options (deny by default) + * + * @access public + * @param string $mode Frame option mode + * @param array $urls Allowed urls for the given mode + */ public function xframe($mode = 'DENY', array $urls = array()) { header('X-Frame-Options: '.$mode.' '.implode(' ', $urls)); diff --git a/app/Core/Router.php b/app/Core/Router.php index a7c9764c..40610996 100644 --- a/app/Core/Router.php +++ b/app/Core/Router.php @@ -38,7 +38,7 @@ class Router * Constructor * * @access public - * @param Core\Registry $registry Registry instance + * @param Registry $registry Registry instance * @param string $controller Controller name * @param string $action Action name */ diff --git a/app/Core/Session.php b/app/Core/Session.php index 0c3ec2d9..6ce1bd40 100644 --- a/app/Core/Session.php +++ b/app/Core/Session.php @@ -2,13 +2,33 @@ namespace Core; +/** + * Session class + * + * @package core + * @author Frederic Guillot + */ class Session { + /** + * Sesion lifetime + * + * @var integer + */ const SESSION_LIFETIME = 86400; // 1 day + /** + * Open a session + * + * @access public + * @param string $base_path Cookie path + * @param string $save_path Custom session save path + */ public function open($base_path = '/', $save_path = '') { - if ($save_path !== '') session_save_path($save_path); + if ($save_path !== '') { + session_save_path($save_path); + } // HttpOnly and secure flags for session cookie session_set_cookie_params( @@ -39,16 +59,33 @@ class Session } } + /** + * Destroy the session + * + * @access public + */ public function close() { session_destroy(); } + /** + * Register a flash message (success notification) + * + * @access public + * @param string $message Message + */ public function flash($message) { $_SESSION['flash_message'] = $message; } + /** + * Register a flash error message (error notification) + * + * @access public + * @param string $message Message + */ public function flashError($message) { $_SESSION['flash_error_message'] = $message; diff --git a/app/Core/Translator.php b/app/Core/Translator.php index be0be66a..015a76cb 100644 --- a/app/Core/Translator.php +++ b/app/Core/Translator.php @@ -121,7 +121,7 @@ class Translator * Get an identifier from the translations or return the default * * @access public - * @param string $idendifier Locale identifier + * @param string $identifier Locale identifier * @param string $default Default value * @return string */ diff --git a/app/Model/Action.php b/app/Model/Action.php index d1b97ebc..7cd917e9 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -213,7 +213,7 @@ class Action extends Base * @access public * @param string $name Action class name * @param integer $project_id Project id - * @return mixed Action Instance + * @return \Core\Listener Action Instance * @throw LogicException */ public function load($name, $project_id) diff --git a/app/Model/Category.php b/app/Model/Category.php index 9be37f9d..58eba403 100644 --- a/app/Model/Category.php +++ b/app/Model/Category.php @@ -106,7 +106,7 @@ class Category extends Base * Validate category creation * * @access public - * @param array $array Form values + * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateCreation(array $values) @@ -128,7 +128,7 @@ class Category extends Base * Validate category modification * * @access public - * @param array $array Form values + * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateModification(array $values) diff --git a/app/Model/Config.php b/app/Model/Config.php index 994f0bc8..9748f38e 100644 --- a/app/Model/Config.php +++ b/app/Model/Config.php @@ -57,9 +57,9 @@ class Config extends Base * Get a config variable from the session or the database * * @access public - * @param string $name Parameter name + * @param string $name Parameter name * @param string $default_value Default value of the parameter - * @return mixed + * @return string */ public function get($name, $default_value = '') { diff --git a/app/Model/File.php b/app/Model/File.php index b7015acc..41ecfba1 100644 --- a/app/Model/File.php +++ b/app/Model/File.php @@ -2,9 +2,6 @@ namespace Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; - /** * File model * @@ -111,7 +108,7 @@ class File extends Base * @param integer $project_id Project id * @param integer $task_id Task id * @param string $filename Filename - * @return bool + * @return string */ public function generatePath($project_id, $task_id, $filename) { diff --git a/app/Model/Project.php b/app/Model/Project.php index 85294830..9fbb0806 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -473,7 +473,7 @@ class Project extends Base * Validate project creation * * @access public - * @param array $array Form values + * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateCreation(array $values) @@ -494,7 +494,7 @@ class Project extends Base * Validate project modification * * @access public - * @param array $array Form values + * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateModification(array $values) @@ -517,7 +517,7 @@ class Project extends Base * Validate allowed users * * @access public - * @param array $array Form values + * @param array $values Form values * @return array $valid, $errors [0] = Success or not, [1] = List of errors */ public function validateUserAccess(array $values) diff --git a/app/Templates/board_public.php b/app/Templates/board_public.php index 0808079e..f90dc01b 100644 --- a/app/Templates/board_public.php +++ b/app/Templates/board_public.php @@ -19,54 +19,9 @@ <?php foreach ($columns as $column): ?> <td class="column <?= $column['task_limit'] && count($column['tasks']) > $column['task_limit'] ? 'task-limit-warning' : '' ?>"> <?php foreach ($column['tasks'] as $task): ?> - <div class="task task-<?= $task['color_id'] ?>"> + <div class="task-board task-<?= $task['color_id'] ?>"> - #<?= $task['id'] ?> - - - <span class="task-user"> - <?php if (! empty($task['owner_id'])): ?> - <?= t('Assigned to %s', $task['username']) ?> - <?php else: ?> - <span class="task-nobody"><?= t('Nobody assigned') ?></span> - <?php endif ?> - </span> - - <?php if ($task['score']): ?> - <span class="task-score"><?= Helper\escape($task['score']) ?></span> - <?php endif ?> - - <div class="task-title"> - <?= Helper\escape($task['title']) ?> - </div> - - <?php if ($task['category_id']): ?> - <div class="task-category-container"> - <span class="task-category"> - <?= Helper\in_list($task['category_id'], $categories) ?> - </span> - </div> - <?php endif ?> - - <?php if (! empty($task['date_due']) || ! empty($task['nb_comments']) || ! empty($task['description'])): ?> - <div class="task-footer"> - - <?php if (! empty($task['date_due'])): ?> - <div class="task-date"> - <?= dt('%B %e, %G', $task['date_due']) ?> - </div> - <?php endif ?> - - <div class="task-icons"> - <?php if (! empty($task['nb_comments'])): ?> - <?= $task['nb_comments'] ?> <i class="fa fa-comment-o" title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>"></i> - <?php endif ?> - - <?php if (! empty($task['description'])): ?> - <i class="fa fa-file-text-o" title="<?= t('Description') ?>"></i> - <?php endif ?> - </div> - </div> - <?php endif ?> + <?= Helper\template('board_task', array('task' => $task, 'categories' => $categories, 'not_editable' => true)) ?> </div> <?php endforeach ?> diff --git a/app/Templates/board_show.php b/app/Templates/board_show.php index 78f9dd50..e5cd9ceb 100644 --- a/app/Templates/board_show.php +++ b/app/Templates/board_show.php @@ -26,63 +26,14 @@ data-task-limit="<?= $column['task_limit'] ?>" > <?php foreach ($column['tasks'] as $task): ?> - <div class="task draggable-item task-<?= $task['color_id'] ?>" + <div class="task-board draggable-item task-<?= $task['color_id'] ?>" data-task-id="<?= $task['id'] ?>" data-owner-id="<?= $task['owner_id'] ?>" data-category-id="<?= $task['category_id'] ?>" data-due-date="<?= $task['date_due'] ?>" title="<?= t('View this task') ?>"> - <a href="?controller=task&action=edit&task_id=<?= $task['id'] ?>" title="<?= t('Edit this task') ?>">#<?= $task['id'] ?></a> - - - <span class="task-user"> - <?php if (! empty($task['owner_id'])): ?> - <a href="?controller=board&action=assign&task_id=<?= $task['id'] ?>" title="<?= t('Change assignee') ?>"><?= t('Assigned to %s', $task['username']) ?></a> - <?php else: ?> - <a href="?controller=board&action=assign&task_id=<?= $task['id'] ?>" title="<?= t('Change assignee') ?>" class="task-nobody"><?= t('Nobody assigned') ?></a> - <?php endif ?> - </span> - - <?php if ($task['score']): ?> - <span class="task-score"><?= Helper\escape($task['score']) ?></span> - <?php endif ?> - - <div class="task-title"> - <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['title']) ?></a> - </div> - - <?php if ($task['category_id']): ?> - <div class="task-category-container"> - <span class="task-category"> - <?= Helper\in_list($task['category_id'], $categories) ?> - </span> - </div> - <?php endif ?> - - <?php if (! empty($task['date_due']) || ! empty($task['nb_files']) || ! empty($task['nb_comments']) || ! empty($task['description'])): ?> - <div class="task-footer"> - - <?php if (! empty($task['date_due'])): ?> - <div class="task-date"> - <?= dt('%B %e, %G', $task['date_due']) ?> - </div> - <?php endif ?> - - <div class="task-icons"> - <?php if (! empty($task['nb_files'])): ?> - <?= $task['nb_files'] ?> <i class="fa fa-paperclip"></i> - <?php endif ?> - - <?php if (! empty($task['nb_comments'])): ?> - <?= $task['nb_comments'] ?> <i class="fa fa-comment-o" title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>"></i> - <?php endif ?> - - <?php if (! empty($task['description'])): ?> - <i class="fa fa-file-text-o" title="<?= t('Description') ?>"></i> - <?php endif ?> - </div> - </div> - <?php endif ?> + <?= Helper\template('board_task', array('task' => $task, 'categories' => $categories)) ?> </div> <?php endforeach ?> diff --git a/app/Templates/board_task.php b/app/Templates/board_task.php new file mode 100644 index 00000000..fa745ac1 --- /dev/null +++ b/app/Templates/board_task.php @@ -0,0 +1,76 @@ +<?php if (isset($not_editable)): ?> + + #<?= $task['id'] ?> - + + <span class="task-board-user"> + <?php if (! empty($task['owner_id'])): ?> + <?= t('Assigned to %s', $task['username']) ?> + <?php else: ?> + <span class="task-board-nobody"><?= t('Nobody assigned') ?></span> + <?php endif ?> + </span> + + <?php if ($task['score']): ?> + <span class="task-score"><?= Helper\escape($task['score']) ?></span> + <?php endif ?> + + <div class="task-board-title"> + <?= Helper\escape($task['title']) ?> + </div> + +<?php else: ?> + + <a href="?controller=task&action=edit&task_id=<?= $task['id'] ?>" title="<?= t('Edit this task') ?>">#<?= $task['id'] ?></a> - + + <span class="task-board-user"> + <?php if (! empty($task['owner_id'])): ?> + <a href="?controller=board&action=assign&task_id=<?= $task['id'] ?>" title="<?= t('Change assignee') ?>"><?= t('Assigned to %s', $task['username']) ?></a> + <?php else: ?> + <a href="?controller=board&action=assign&task_id=<?= $task['id'] ?>" title="<?= t('Change assignee') ?>" class="task-board-nobody"><?= t('Nobody assigned') ?></a> + <?php endif ?> + </span> + + <?php if ($task['score']): ?> + <span class="task-score"><?= Helper\escape($task['score']) ?></span> + <?php endif ?> + + <div class="task-board-title"> + <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['title']) ?></a> + </div> + +<?php endif ?> + + +<?php if ($task['category_id']): ?> +<div class="task-board-category-container"> + <span class="task-board-category"> + <?= Helper\in_list($task['category_id'], $categories) ?> + </span> +</div> +<?php endif ?> + + +<?php if (! empty($task['date_due']) || ! empty($task['nb_files']) || ! empty($task['nb_comments']) || ! empty($task['description'])): ?> +<div class="task-board-footer"> + + <?php if (! empty($task['date_due'])): ?> + <div class="task-board-date"> + <?= dt('%B %e, %G', $task['date_due']) ?> + </div> + <?php endif ?> + + <div class="task-board-icons"> + <?php if (! empty($task['nb_files'])): ?> + <?= $task['nb_files'] ?> <i class="fa fa-paperclip" title="<?= t('Attachments') ?>"></i> + <?php endif ?> + + <?php if (! empty($task['nb_comments'])): ?> + <?= $task['nb_comments'] ?> <i class="fa fa-comment-o" title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>"></i> + <?php endif ?> + + <?php if (! empty($task['description'])): ?> + <i class="fa fa-file-text-o" title="<?= t('Description') ?>"></i> + <?php endif ?> + </div> +</div> +<?php endif ?>
\ No newline at end of file diff --git a/app/Templates/project_search.php b/app/Templates/project_search.php index 3594fd09..7826ba63 100644 --- a/app/Templates/project_search.php +++ b/app/Templates/project_search.php @@ -24,69 +24,7 @@ <?php if (empty($tasks) && ! empty($values['search'])): ?> <p class="alert"><?= t('Nothing found.') ?></p> <?php elseif (! empty($tasks)): ?> - <table> - <tr> - <th><?= t('Id') ?></th> - <th><?= t('Column') ?></th> - <th><?= t('Category') ?></th> - <th><?= t('Title') ?></th> - <th><?= t('Assignee') ?></th> - <th><?= t('Due date') ?></th> - <th><?= t('Date created') ?></th> - <th><?= t('Date completed') ?></th> - <th><?= t('Status') ?></th> - </tr> - <?php foreach ($tasks as $task): ?> - <tr> - <td class="task task-<?= $task['color_id'] ?>"> - <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['id']) ?></a> - </td> - <td> - <?= Helper\in_list($task['column_id'], $columns) ?> - </td> - <td> - <?= Helper\in_list($task['category_id'], $categories, '') ?> - </td> - <td> - <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['title']) ?></a> - <div class="task-table-icons"> - <?php if (! empty($task['nb_comments'])): ?> - <?= $task['nb_comments'] ?> <i class="fa fa-comment-o" title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>"></i> - <?php endif ?> - - <?php if (! empty($task['description'])): ?> - <i class="fa fa-file-text-o" title="<?= t('Description') ?>"></i> - <?php endif ?> - </div> - </td> - <td> - <?php if ($task['username']): ?> - <?= Helper\escape($task['username']) ?> - <?php else: ?> - <?= t('Unassigned') ?> - <?php endif ?> - </td> - <td> - <?= dt('%B %e, %G', $task['date_due']) ?> - </td> - <td> - <?= dt('%B %e, %G at %k:%M %p', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %G at %k:%M %p', $task['date_completed']) ?> - <?php endif ?> - </td> - <td> - <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> - <?= t('Open') ?> - <?php else: ?> - <?= t('Closed') ?> - <?php endif ?> - </td> - </tr> - <?php endforeach ?> - </table> + <?= Helper\template('task_table', array('tasks' => $tasks, 'categories' => $categories, 'columns' => $columns)) ?> <?php endif ?> </section> diff --git a/app/Templates/project_tasks.php b/app/Templates/project_tasks.php index 9f4263b8..a820be13 100644 --- a/app/Templates/project_tasks.php +++ b/app/Templates/project_tasks.php @@ -11,61 +11,7 @@ <?php if (empty($tasks)): ?> <p class="alert"><?= t('No task') ?></p> <?php else: ?> - <table> - <tr> - <th><?= t('Id') ?></th> - <th><?= t('Column') ?></th> - <th><?= t('Category') ?></th> - <th><?= t('Title') ?></th> - <th><?= t('Assignee') ?></th> - <th><?= t('Due date') ?></th> - <th><?= t('Date created') ?></th> - <th><?= t('Date completed') ?></th> - </tr> - <?php foreach ($tasks as $task): ?> - <tr> - <td class="task task-<?= $task['color_id'] ?>"> - <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['id']) ?></a> - </td> - <td> - <?= Helper\in_list($task['column_id'], $columns) ?> - </td> - <td> - <?= Helper\in_list($task['category_id'], $categories, '') ?> - </td> - <td> - <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['title']) ?></a> - <div class="task-table-icons"> - <?php if (! empty($task['nb_comments'])): ?> - <?= $task['nb_comments'] ?> <i class="fa fa-comment-o" title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>"></i> - <?php endif ?> - - <?php if (! empty($task['description'])): ?> - <i class="fa fa-file-text-o" title="<?= t('Description') ?>"></i> - <?php endif ?> - </div> - </td> - <td> - <?php if ($task['username']): ?> - <?= Helper\escape($task['username']) ?> - <?php else: ?> - <?= t('Unassigned') ?> - <?php endif ?> - </td> - <td> - <?= dt('%B %e, %G', $task['date_due']) ?> - </td> - <td> - <?= dt('%B %e, %G at %k:%M %p', $task['date_creation']) ?> - </td> - <td> - <?php if ($task['date_completed']): ?> - <?= dt('%B %e, %G at %k:%M %p', $task['date_completed']) ?> - <?php endif ?> - </td> - </tr> - <?php endforeach ?> - </table> + <?= Helper\template('task_table', array('tasks' => $tasks, 'categories' => $categories, 'columns' => $columns)) ?> <?php endif ?> </section> </section>
\ No newline at end of file diff --git a/app/Templates/task_table.php b/app/Templates/task_table.php new file mode 100644 index 00000000..10f79d29 --- /dev/null +++ b/app/Templates/task_table.php @@ -0,0 +1,54 @@ +<table> + <tr> + <th><?= t('Id') ?></th> + <th><?= t('Column') ?></th> + <th><?= t('Category') ?></th> + <th><?= t('Title') ?></th> + <th><?= t('Assignee') ?></th> + <th><?= t('Due date') ?></th> + <th><?= t('Date created') ?></th> + <th><?= t('Date completed') ?></th> + <th><?= t('Status') ?></th> + </tr> + <?php foreach ($tasks as $task): ?> + <tr> + <td class="task-table task-<?= $task['color_id'] ?>"> + <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['id']) ?></a> + </td> + <td> + <?= Helper\in_list($task['column_id'], $columns) ?> + </td> + <td> + <?= Helper\in_list($task['category_id'], $categories, '') ?> + </td> + <td> + <a href="?controller=task&action=show&task_id=<?= $task['id'] ?>" title="<?= t('View this task') ?>"><?= Helper\escape($task['title']) ?></a> + </td> + <td> + <?php if ($task['username']): ?> + <?= Helper\escape($task['username']) ?> + <?php else: ?> + <?= t('Unassigned') ?> + <?php endif ?> + </td> + <td> + <?= dt('%B %e, %G', $task['date_due']) ?> + </td> + <td> + <?= dt('%B %e, %G at %k:%M %p', $task['date_creation']) ?> + </td> + <td> + <?php if ($task['date_completed']): ?> + <?= dt('%B %e, %G at %k:%M %p', $task['date_completed']) ?> + <?php endif ?> + </td> + <td> + <?php if ($task['is_active'] == \Model\Task::STATUS_OPEN): ?> + <?= t('Open') ?> + <?php else: ?> + <?= t('Closed') ?> + <?php endif ?> + </td> + </tr> + <?php endforeach ?> +</table>
\ No newline at end of file diff --git a/assets/css/app.css b/assets/css/app.css index 78fc29bd..fcfe6b1a 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -478,7 +478,7 @@ nav .active a { padding-left: 0; } -/* boards */ +/* board */ .page-header.board { margin-bottom: 0; } @@ -506,6 +506,11 @@ nav .active a { font-size: 0.8em; } +a.filter-on { + font-weight: bold; + color: #333; +} + .public-board { margin-top: 5px; } @@ -523,32 +528,67 @@ nav .active a { background-color: red; } -a.filter-on { +.draggable-item { + cursor: pointer; + user-select: none; +} + +.draggable-placeholder { + border: 2px dashed #000; + background: #fafafa; + height: 70px; + margin-bottom: 10px; +} + +/* task inside the board */ +.task-board { + position: relative; + margin-right: 5px; + margin-bottom: 10px; + border: 1px solid #000; + padding: 5px; + font-size: 95%; +} + +.task-table a, +.task-board a { + color: #000; + text-decoration: none; font-weight: bold; - color: #333; } -.task-title { +.task-table a:focus, +.task-table a:hover, +.task-board a:focus, +.task-board a:hover { + text-decoration: underline; +} + +.task-board-title { margin-top: 10px; font-size: 110%; } -.task-user { +.task-board-title a { + font-weight: normal; +} + +.task-board-user { font-size: 80%; } -.task a.task-nobody { +a.task-board-nobody { font-weight: normal; font-style: italic; color: #444; } -.task-category-container { +.task-board-category-container { text-align: right; padding-bottom: 2px; } -.task-category { +.task-board-category { font-weight: bold; font-size: 0.8em; color: #000; @@ -559,7 +599,11 @@ a.filter-on { padding-left: 5px; } -.task-date { +.task-board-footer { + height: 18px; +} + +.task-board-date { position: absolute; bottom: 0; left: 5px; @@ -567,82 +611,24 @@ a.filter-on { color: #D90000; } -.task-icons { +.task-board-icons { position: absolute; bottom: 0; right: 5px; } -.task-footer { - height: 18px; -} - -.task { - border: 1px solid #000; - padding: 5px; - font-size: 95%; -} - -td.over { - background-color: #f0f0f0; -} - -td div.over { - border: 2px dashed #000; -} - -.draggable-item { - cursor: pointer; - user-select: none; -} - -.draggable-placeholder { - border: 2px dashed #000; - background: #fafafa; - height: 70px; - margin-bottom: 10px; -} - -tr td.task a, -div.task a { - color: #000; - text-decoration: none; - font-weight: bold; -} - -tr td.task a:focus, -tr td.task a:hover, -div.task a:focus, -div.task a:hover { - text-decoration: underline; -} - -div.task-title a { - font-weight: normal; -} - -div.task { - position: relative; - margin-right: 5px; - margin-bottom: 10px; -} - +/* task score */ .task-score { font-weight: bold; position: absolute; } -div.task .task-score { +.task-board .task-score { font-size: 1.5em; right: 5px; top: 0; } -.task-table-icons { - float: right ; - text-align: right; -} - /* task view */ .task-show { position: relative; diff --git a/assets/js/board.js b/assets/js/board.js index 357849e6..f5547310 100644 --- a/assets/js/board.js +++ b/assets/js/board.js @@ -15,7 +15,7 @@ }); // Open assignee popover - $(".task-user a").click(function(e) { + $(".task-boad-user a").click(function(e) { e.preventDefault(); e.stopPropagation(); @@ -60,7 +60,7 @@ $(".column").each(function() { var columnId = $(this).attr("data-column-id"); - $("#column-" + columnId + " .task").each(function(index) { + $("#column-" + columnId + " .task-board").each(function(index) { data.push({ "task_id": parseInt($(this).attr("data-task-id")), "position": index + 1, |