Add categories for projects and tasks
This commit is contained in:
parent
57e40671af
commit
a750b8ab2a
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Action;
|
||||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
/**
|
||||
* Assign a color to a specific category
|
||||
*
|
||||
* @package action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorCategory extends Base
|
||||
{
|
||||
/**
|
||||
* Task model
|
||||
*
|
||||
* @accesss private
|
||||
* @var \Model\Task
|
||||
*/
|
||||
private $task;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param \Model\Task $task Task model instance
|
||||
*/
|
||||
public function __construct($project_id, \Model\Task $task)
|
||||
{
|
||||
parent::__construct($project_id);
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the action (defined by the user)
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'color_id' => t('Color'),
|
||||
'category_id' => t('Category'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the event
|
||||
*
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'category_id',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
if ($data['category_id'] == $this->getParam('category_id')) {
|
||||
|
||||
$this->task->update(array(
|
||||
'id' => $data['task_id'],
|
||||
'color_id' => $this->getParam('color_id'),
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,6 @@ class TaskAssignColorUser extends Base
|
|||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'column_id' => t('Column'),
|
||||
'color_id' => t('Color'),
|
||||
'user_id' => t('Assignee'),
|
||||
);
|
||||
|
|
@ -59,7 +58,6 @@ class TaskAssignColorUser extends Base
|
|||
return array(
|
||||
'task_id',
|
||||
'owner_id',
|
||||
'column_id',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +70,7 @@ class TaskAssignColorUser extends Base
|
|||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
if ($data['column_id'] == $this->getParam('column_id') && $data['owner_id'] == $this->getParam('user_id')) {
|
||||
if ($data['owner_id'] == $this->getParam('user_id')) {
|
||||
|
||||
$this->task->update(array(
|
||||
'id' => $data['task_id'],
|
||||
|
|
|
|||
|
|
@ -484,23 +484,26 @@ nav .active a {
|
|||
}
|
||||
|
||||
.project-menu li {
|
||||
padding-left: 5px;
|
||||
display: inline;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-right: 1px dotted #ccc;
|
||||
}
|
||||
|
||||
.project-menu li:last-child {
|
||||
border: none;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.project-menu ul {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.project-menu a {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.project-menu {
|
||||
text-align: right;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.public-board {
|
||||
|
|
@ -540,7 +543,26 @@ a.filter-on {
|
|||
color: #444;
|
||||
}
|
||||
|
||||
.task-category-container {
|
||||
text-align: right;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.task-category {
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
color: #000;
|
||||
border: 1px solid #555;
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.task-date {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 5px;
|
||||
font-weight: bold;
|
||||
color: #D90000;
|
||||
}
|
||||
|
|
@ -552,7 +574,7 @@ a.filter-on {
|
|||
}
|
||||
|
||||
.task-footer {
|
||||
margin-top: 10px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.task {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
$("#board").remove();
|
||||
$("#main").append(data);
|
||||
board_load_events();
|
||||
filter_apply(filter_get_user_id(), filter_has_due_date());
|
||||
filter_apply();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -96,32 +96,25 @@
|
|||
$("#main").append(data);
|
||||
board_unload_events();
|
||||
board_load_events();
|
||||
filter_apply(filter_get_user_id(), filter_has_due_date());
|
||||
filter_apply();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get the selected user id
|
||||
function filter_get_user_id()
|
||||
{
|
||||
return $("#form-user_id").val();
|
||||
}
|
||||
|
||||
// Return true if the filter is activated
|
||||
function filter_has_due_date()
|
||||
{
|
||||
return $("#filter-due-date").hasClass("filter-on");
|
||||
}
|
||||
|
||||
// Apply user or date filter (change tasks opacity)
|
||||
function filter_apply(selectedUserId, filterDueDate)
|
||||
function filter_apply()
|
||||
{
|
||||
var selectedUserId = $("#form-user_id").val();
|
||||
var selectedCategoryId = $("#form-category_id").val();
|
||||
var filterDueDate = $("#filter-due-date").hasClass("filter-on");
|
||||
|
||||
$("[data-task-id]").each(function(index, item) {
|
||||
|
||||
var ownerId = item.getAttribute("data-owner-id");
|
||||
var dueDate = item.getAttribute("data-due-date");
|
||||
var categoryId = item.getAttribute("data-category-id");
|
||||
|
||||
if (ownerId != selectedUserId && selectedUserId != -1) {
|
||||
item.style.opacity = "0.2";
|
||||
|
|
@ -133,19 +126,23 @@
|
|||
if (filterDueDate && (dueDate == "" || dueDate == "0")) {
|
||||
item.style.opacity = "0.2";
|
||||
}
|
||||
|
||||
if (categoryId != selectedCategoryId && selectedCategoryId != -1) {
|
||||
item.style.opacity = "0.2";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load filter events
|
||||
function filter_load_events()
|
||||
{
|
||||
$("#form-user_id").change(function() {
|
||||
filter_apply(filter_get_user_id(), filter_has_due_date());
|
||||
});
|
||||
$("#form-user_id").change(filter_apply);
|
||||
|
||||
$("#form-category_id").change(filter_apply);
|
||||
|
||||
$("#filter-due-date").click(function(e) {
|
||||
$(this).toggleClass("filter-on");
|
||||
filter_apply(filter_get_user_id(), filter_has_due_date());
|
||||
filter_apply();
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require __DIR__.'/core/translator.php';
|
|||
|
||||
$registry = new Core\Registry;
|
||||
|
||||
$registry->db_version = 15;
|
||||
$registry->db_version = 16;
|
||||
|
||||
$registry->db = function() use ($registry) {
|
||||
require __DIR__.'/vendor/PicoDb/Database.php';
|
||||
|
|
@ -110,6 +110,11 @@ $registry->google = function() use ($registry) {
|
|||
return new \Model\Google($registry->shared('db'), $registry->shared('event'));
|
||||
};
|
||||
|
||||
$registry->category = function() use ($registry) {
|
||||
require_once __DIR__.'/models/category.php';
|
||||
return new \Model\Category($registry->shared('db'), $registry->shared('event'));
|
||||
};
|
||||
|
||||
if (file_exists('config.php')) require 'config.php';
|
||||
|
||||
// Board refresh frequency in seconds for the public board view
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class Action extends Base
|
|||
'users_list' => $this->project->getUsersList($project['id'], false),
|
||||
'projects_list' => $this->project->getList(false),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($project['id'], false),
|
||||
'menu' => 'projects',
|
||||
'title' => t('Automatic actions')
|
||||
)));
|
||||
|
|
@ -68,6 +69,7 @@ class Action extends Base
|
|||
'users_list' => $this->project->getUsersList($project['id'], false),
|
||||
'projects_list' => $this->project->getList(false),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($project['id'], false),
|
||||
'project' => $project,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Automatic actions')
|
||||
|
|
|
|||
|
|
@ -130,6 +130,14 @@ abstract class Base
|
|||
*/
|
||||
protected $google;
|
||||
|
||||
/**
|
||||
* Category model
|
||||
*
|
||||
* @accesss protected
|
||||
* @var \Model\Category
|
||||
*/
|
||||
protected $category;
|
||||
|
||||
/**
|
||||
* Event instance
|
||||
*
|
||||
|
|
@ -157,6 +165,7 @@ abstract class Base
|
|||
$this->rememberMe = $registry->rememberMe;
|
||||
$this->lastLogin = $registry->lastLogin;
|
||||
$this->google = $registry->google;
|
||||
$this->category = $registry->category;
|
||||
$this->event = $registry->shared('event');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ class Board extends Base
|
|||
$this->response->html($this->template->layout('board_public', array(
|
||||
'project' => $project,
|
||||
'columns' => $this->board->get($project['id']),
|
||||
'categories' => $this->category->getList($project['id'], false),
|
||||
'title' => $project['name'],
|
||||
'no_layout' => true,
|
||||
'auto_refresh' => true,
|
||||
|
|
@ -195,6 +196,7 @@ class Board extends Base
|
|||
'current_project_id' => $project_id,
|
||||
'current_project_name' => $projects[$project_id],
|
||||
'board' => $this->board->get($project_id),
|
||||
'categories' => $this->category->getList($project_id, true, true),
|
||||
'menu' => 'boards',
|
||||
'title' => $projects[$project_id]
|
||||
)));
|
||||
|
|
@ -369,7 +371,11 @@ class Board extends Base
|
|||
}
|
||||
|
||||
$this->response->html(
|
||||
$this->template->load('board_show', array('current_project_id' => $project_id, 'board' => $this->board->get($project_id))),
|
||||
$this->template->load('board_show', array(
|
||||
'current_project_id' => $project_id,
|
||||
'board' => $this->board->get($project_id),
|
||||
'categories' => $this->category->getList($project_id, false),
|
||||
)),
|
||||
201
|
||||
);
|
||||
}
|
||||
|
|
@ -390,7 +396,11 @@ class Board extends Base
|
|||
|
||||
if ($this->project->isModifiedSince($project_id, $timestamp)) {
|
||||
$this->response->html(
|
||||
$this->template->load('board_show', array('current_project_id' => $project_id, 'board' => $this->board->get($project_id)))
|
||||
$this->template->load('board_show', array(
|
||||
'current_project_id' => $project_id,
|
||||
'board' => $this->board->get($project_id),
|
||||
'categories' => $this->category->getList($project_id, false),
|
||||
))
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
<?php
|
||||
|
||||
namespace Controller;
|
||||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
/**
|
||||
* Categories management
|
||||
*
|
||||
* @package controller
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Category extends Base
|
||||
{
|
||||
/**
|
||||
* Get the current project (common method between actions)
|
||||
*
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function getProject()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
$project = $this->project->getById($project_id);
|
||||
|
||||
if (! $project) {
|
||||
$this->session->flashError(t('Project not found.'));
|
||||
$this->response->redirect('?controller=project');
|
||||
}
|
||||
|
||||
return $project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category (common method between actions)
|
||||
*
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function getCategory($project_id)
|
||||
{
|
||||
$category = $this->category->getById($this->request->getIntegerParam('category_id'));
|
||||
|
||||
if (! $category) {
|
||||
$this->session->flashError(t('Category not found.'));
|
||||
$this->response->redirect('?controller=category&action=index&project_id='.$project_id);
|
||||
}
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of categories for a given project
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
|
||||
$this->response->html($this->template->layout('category_index', array(
|
||||
'categories' => $this->category->getList($project['id'], false),
|
||||
'values' => array('project_id' => $project['id']),
|
||||
'errors' => array(),
|
||||
'project' => $project,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Categories')
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and save a new project
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
|
||||
$values = $this->request->getValues();
|
||||
list($valid, $errors) = $this->category->validateCreation($values);
|
||||
|
||||
if ($valid) {
|
||||
|
||||
if ($this->category->create($values)) {
|
||||
$this->session->flash(t('Your category have been created successfully.'));
|
||||
$this->response->redirect('?controller=category&action=index&project_id='.$project['id']);
|
||||
}
|
||||
else {
|
||||
$this->session->flashError(t('Unable to create your category.'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->response->html($this->template->layout('category_index', array(
|
||||
'categories' => $this->category->getList($project['id'], false),
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
'project' => $project,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Categories')
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a category (display the form)
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
$category = $this->getCategory($project['id']);
|
||||
|
||||
$this->response->html($this->template->layout('category_edit', array(
|
||||
'values' => $category,
|
||||
'errors' => array(),
|
||||
'project' => $project,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Categories')
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a category (validate the form and update the database)
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
|
||||
$values = $this->request->getValues();
|
||||
list($valid, $errors) = $this->category->validateModification($values);
|
||||
|
||||
if ($valid) {
|
||||
|
||||
if ($this->category->update($values)) {
|
||||
$this->session->flash(t('Your category have been updated successfully.'));
|
||||
$this->response->redirect('?controller=category&action=index&project_id='.$project['id']);
|
||||
}
|
||||
else {
|
||||
$this->session->flashError(t('Unable to update your category.'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->response->html($this->template->layout('category_edit', array(
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
'project' => $project,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Categories')
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirmation dialog before removing a category
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function confirm()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
$category = $this->getCategory($project['id']);
|
||||
|
||||
$this->response->html($this->template->layout('category_remove', array(
|
||||
'project' => $project,
|
||||
'category' => $category,
|
||||
'menu' => 'projects',
|
||||
'title' => t('Remove a category')
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a category
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
$project = $this->getProject();
|
||||
$category = $this->getCategory($project['id']);
|
||||
|
||||
if ($this->category->remove($category['id'])) {
|
||||
$this->session->flash(t('Category removed successfully.'));
|
||||
} else {
|
||||
$this->session->flashError(t('Unable to remove this category.'));
|
||||
}
|
||||
|
||||
$this->response->redirect('?controller=category&action=index&project_id='.$project['id']);
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ class Project extends Base
|
|||
array('column' => 'project_id', 'operator' => 'eq', 'value' => $project_id),
|
||||
'or' => array(
|
||||
array('column' => 'title', 'operator' => 'like', 'value' => '%'.$search.'%'),
|
||||
array('column' => 'description', 'operator' => 'like', 'value' => '%'.$search.'%'),
|
||||
//array('column' => 'description', 'operator' => 'like', 'value' => '%'.$search.'%'),
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -72,6 +72,7 @@ class Project extends Base
|
|||
'menu' => 'projects',
|
||||
'project' => $project,
|
||||
'columns' => $this->board->getColumnsList($project_id),
|
||||
'categories' => $this->category->getList($project['id'], false),
|
||||
'title' => $project['name'].($nb_tasks > 0 ? ' ('.$nb_tasks.')' : '')
|
||||
)));
|
||||
}
|
||||
|
|
@ -105,6 +106,7 @@ class Project extends Base
|
|||
'menu' => 'projects',
|
||||
'project' => $project,
|
||||
'columns' => $this->board->getColumnsList($project_id),
|
||||
'categories' => $this->category->getList($project['id'], false),
|
||||
'tasks' => $tasks,
|
||||
'nb_tasks' => $nb_tasks,
|
||||
'title' => $project['name'].' ('.$nb_tasks.')'
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class Task extends Base
|
|||
'project_id' => $this->request->getIntegerParam('project_id', $defaultProject['id']),
|
||||
'owner_id' => $this->request->getIntegerParam('owner_id'),
|
||||
'column_id' => $this->request->getIntegerParam('column_id'),
|
||||
'category_id' => $this->request->getIntegerParam('category_id'),
|
||||
);
|
||||
|
||||
if ($values['column_id'] == 0) {
|
||||
|
|
@ -121,6 +122,7 @@ class Task extends Base
|
|||
'columns_list' => $this->board->getColumnsList($project_id),
|
||||
'users_list' => $this->project->getUsersList($project_id),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($project_id),
|
||||
'menu' => 'tasks',
|
||||
'title' => t('New task')
|
||||
)));
|
||||
|
|
@ -164,6 +166,7 @@ class Task extends Base
|
|||
'columns_list' => $this->board->getColumnsList($values['project_id']),
|
||||
'users_list' => $this->project->getUsersList($values['project_id']),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($values['project_id']),
|
||||
'menu' => 'tasks',
|
||||
'title' => t('New task')
|
||||
)));
|
||||
|
|
@ -196,6 +199,7 @@ class Task extends Base
|
|||
'columns_list' => $this->board->getColumnsList($task['project_id']),
|
||||
'users_list' => $this->project->getUsersList($task['project_id']),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($task['project_id']),
|
||||
'menu' => 'tasks',
|
||||
'title' => t('Edit a task')
|
||||
)));
|
||||
|
|
@ -230,6 +234,7 @@ class Task extends Base
|
|||
'columns_list' => $this->board->getColumnsList($values['project_id']),
|
||||
'users_list' => $this->project->getUsersList($values['project_id']),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($values['project_id']),
|
||||
'menu' => 'tasks',
|
||||
'title' => t('Edit a task')
|
||||
)));
|
||||
|
|
@ -383,6 +388,7 @@ class Task extends Base
|
|||
'columns_list' => $this->board->getColumnsList($task['project_id']),
|
||||
'users_list' => $this->project->getUsersList($task['project_id']),
|
||||
'colors_list' => $this->task->getColors(),
|
||||
'categories_list' => $this->category->getList($task['project_id']),
|
||||
'duplicate' => true,
|
||||
'menu' => 'tasks',
|
||||
'title' => t('New task')
|
||||
|
|
|
|||
|
|
@ -112,13 +112,13 @@ function contains($haystack, $needle)
|
|||
return strpos($haystack, $needle) !== false;
|
||||
}
|
||||
|
||||
function in_list($id, array $listing)
|
||||
function in_list($id, array $listing, $default_value = '?')
|
||||
{
|
||||
if (isset($listing[$id])) {
|
||||
return escape($listing[$id]);
|
||||
}
|
||||
|
||||
return '?';
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
function error_class(array $errors, $name)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ List of available events
|
|||
- Task creation
|
||||
- Open a closed task
|
||||
- Closing a task
|
||||
- Task creation or modification
|
||||
|
||||
List of available actions
|
||||
-------------------------
|
||||
|
|
@ -33,6 +34,7 @@ List of available actions
|
|||
- Assign the task to the person who does the action
|
||||
- Duplicate the task to another project
|
||||
- Assign a color to a specific user
|
||||
- Assign a color to a specific category
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
|
@ -65,8 +67,14 @@ Let's say we have two projects "Customer orders" and "Production", once the orde
|
|||
- Choose the action: **Duplicate the task to another project**
|
||||
- Define the action parameters: **Column = Validated** and **Project = Production**
|
||||
|
||||
### When I create a new task in the column "To do", assign a specific color to the user Bob
|
||||
### I want to assign a specific color to the user Bob
|
||||
|
||||
- Choose the event: **Task creation**
|
||||
- Choose the action: **Assign a color to a specific user**
|
||||
- Define the action parameters: **Column = To do**, **Color = Green** and **Assignee = Bob**
|
||||
- Define the action parameters: **Color = Green** and **Assignee = Bob**
|
||||
|
||||
### I want to assign a specific color to the category "Feature Request"
|
||||
|
||||
- Choose the event: **Task creation or modification**
|
||||
- Choose the action: **Assign a color to a specific category**
|
||||
- Define the action parameters: **Color = Blue** and **Category = Feature Request**
|
||||
|
|
|
|||
|
|
@ -309,4 +309,25 @@ return array(
|
|||
// 'Unable to remove this task.' => '',
|
||||
// 'Remove a task' => '',
|
||||
// 'Do you really want to remove this task: "%s"?' => '',
|
||||
// 'Assign a color to a specific category' => '',
|
||||
// 'Task creation or modification' => '',
|
||||
// 'Category' => '',
|
||||
// 'Category:' => '',
|
||||
// 'Categories' => '',
|
||||
// 'Category not found.' => '',
|
||||
// 'Your category have been created successfully.' => '',
|
||||
// 'Unable to create your category.' => '',
|
||||
// 'Your category have been updated successfully.' => '',
|
||||
// 'Unable to update your category.' => '',
|
||||
// 'Remove a category' => '',
|
||||
// 'Category removed successfully.' => '',
|
||||
// 'Unable to remove this category.' => '',
|
||||
// 'Category modification for the project "%s"' => '',
|
||||
// 'Category Name' => '',
|
||||
// 'Categories for the project "%s"' => '',
|
||||
// 'Add a new category' => '',
|
||||
// 'Do you really want to remove this category: "%s"?' => '',
|
||||
// 'Filter by category' => '',
|
||||
// 'All categories' => '',
|
||||
// 'No category' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -309,4 +309,25 @@ return array(
|
|||
'Unable to remove this task.' => 'Impossible de supprimer cette tâche.',
|
||||
'Remove a task' => 'Supprimer une tâche',
|
||||
'Do you really want to remove this task: "%s"?' => 'Voulez-vous vraiment supprimer cette tâche « %s » ?',
|
||||
'Assign a color to a specific category' => 'Assigner une couleur à une catégorie spécifique',
|
||||
'Task creation or modification' => 'Création ou modification d\'une tâche',
|
||||
'Category' => 'Catégorie',
|
||||
'Category:' => 'Catégorie :',
|
||||
'Categories' => 'Catégories',
|
||||
'Category not found.' => 'Catégorie introuvable',
|
||||
'Your category have been created successfully.' => 'Votre catégorie a été créé avec succès.',
|
||||
'Unable to create your category.' => 'Impossible de créer votre catégorie.',
|
||||
'Your category have been updated successfully.' => 'Votre catégorie a été mise à jour avec succès.',
|
||||
'Unable to update your category.' => 'Impossible de mettre à jour votre catégorie.',
|
||||
'Remove a category' => 'Supprimer une catégorie',
|
||||
'Category removed successfully.' => 'Catégorie supprimée avec succès.',
|
||||
'Unable to remove this category.' => 'Impossible de supprimer cette catégorie.',
|
||||
'Category modification for the project "%s"' => 'Modification d\'une catégorie pour le projet « %s »',
|
||||
'Category Name' => 'Nom de la catégorie',
|
||||
'Categories for the project "%s"' => 'Catégories du projet « %s »',
|
||||
'Add a new category' => 'Ajouter une nouvelle catégorie',
|
||||
'Do you really want to remove this category: "%s"?' => 'Voulez-vous vraiment supprimer cette catégorie « %s » ?',
|
||||
'Filter by category' => 'Filtrer par catégorie',
|
||||
'All categories' => 'Toutes les catégories',
|
||||
'No category' => 'Aucune catégorie',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -314,4 +314,25 @@ return array(
|
|||
// 'Unable to remove this task.' => '',
|
||||
// 'Remove a task' => '',
|
||||
// 'Do you really want to remove this task: "%s"?' => '',
|
||||
// 'Assign a color to a specific category' => '',
|
||||
// 'Task creation or modification' => '',
|
||||
// 'Category' => '',
|
||||
// 'Category:' => '',
|
||||
// 'Categories' => '',
|
||||
// 'Category not found.' => '',
|
||||
// 'Your category have been created successfully.' => '',
|
||||
// 'Unable to create your category.' => '',
|
||||
// 'Your category have been updated successfully.' => '',
|
||||
// 'Unable to update your category.' => '',
|
||||
// 'Remove a category' => '',
|
||||
// 'Category removed successfully.' => '',
|
||||
// 'Unable to remove this category.' => '',
|
||||
// 'Category modification for the project "%s"' => '',
|
||||
// 'Category Name' => '',
|
||||
// 'Categories for the project "%s"' => '',
|
||||
// 'Add a new category' => '',
|
||||
// 'Do you really want to remove this category: "%s"?' => '',
|
||||
// 'Filter by category' => '',
|
||||
// 'All categories' => '',
|
||||
// 'No category' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -310,4 +310,25 @@ return array(
|
|||
// 'Unable to remove this task.' => '',
|
||||
// 'Remove a task' => '',
|
||||
// 'Do you really want to remove this task: "%s"?' => '',
|
||||
// 'Assign a color to a specific category' => '',
|
||||
// 'Task creation or modification' => '',
|
||||
// 'Category' => '',
|
||||
// 'Category:' => '',
|
||||
// 'Categories' => '',
|
||||
// 'Category not found.' => '',
|
||||
// 'Your category have been created successfully.' => '',
|
||||
// 'Unable to create your category.' => '',
|
||||
// 'Your category have been updated successfully.' => '',
|
||||
// 'Unable to update your category.' => '',
|
||||
// 'Remove a category' => '',
|
||||
// 'Category removed successfully.' => '',
|
||||
// 'Unable to remove this category.' => '',
|
||||
// 'Category modification for the project "%s"' => '',
|
||||
// 'Category Name' => '',
|
||||
// 'Categories for the project "%s"' => '',
|
||||
// 'Add a new category' => '',
|
||||
// 'Do you really want to remove this category: "%s"?' => '',
|
||||
// 'Filter by category' => '',
|
||||
// 'All categories' => '',
|
||||
// 'No category' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class Action extends Base
|
|||
'TaskAssignCurrentUser' => t('Assign the task to the person who does the action'),
|
||||
'TaskDuplicateAnotherProject' => t('Duplicate the task to another project'),
|
||||
'TaskAssignColorUser' => t('Assign a color to a specific user'),
|
||||
'TaskAssignColorCategory' => t('Assign a color to a specific category'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +63,7 @@ class Action extends Base
|
|||
Task::EVENT_CREATE => t('Task creation'),
|
||||
Task::EVENT_OPEN => t('Open a closed task'),
|
||||
Task::EVENT_CLOSE => t('Closing a task'),
|
||||
Task::EVENT_CREATE_UPDATE => t('Task creation or modification'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +241,10 @@ class Action extends Base
|
|||
require_once __DIR__.'/../actions/task_assign_color_user.php';
|
||||
$className = '\Action\TaskAssignColorUser';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
case 'TaskAssignColorCategory':
|
||||
require_once __DIR__.'/../actions/task_assign_color_category.php';
|
||||
$className = '\Action\TaskAssignColorCategory';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
default:
|
||||
throw new \LogicException('Action not found: '.$name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
/**
|
||||
* Category model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Category extends Base
|
||||
{
|
||||
/**
|
||||
* SQL table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TABLE = 'project_has_categories';
|
||||
|
||||
/**
|
||||
* Get a category by the id
|
||||
*
|
||||
* @access public
|
||||
* @param integer $category_id Category id
|
||||
* @return array
|
||||
*/
|
||||
public function getById($category_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('id', $category_id)->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of all categories
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param bool $prepend_none If true, prepend to the list the value 'None'
|
||||
* @param bool $prepend_all If true, prepend to the list the value 'All'
|
||||
* @return array
|
||||
*/
|
||||
public function getList($project_id, $prepend_none = true, $prepend_all = false)
|
||||
{
|
||||
$listing = $this->db->table(self::TABLE)
|
||||
->eq('project_id', $project_id)
|
||||
->asc('name')
|
||||
->listing('id', 'name');
|
||||
|
||||
$prepend = array();
|
||||
|
||||
if ($prepend_all) {
|
||||
$prepend[-1] = t('All categories');
|
||||
}
|
||||
|
||||
if ($prepend_none) {
|
||||
$prepend[0] = t('No category');
|
||||
}
|
||||
|
||||
return $prepend + $listing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a category
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return bool
|
||||
*/
|
||||
public function create(array $values)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->save($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a category
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return bool
|
||||
*/
|
||||
public function update(array $values)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a category
|
||||
*
|
||||
* @access public
|
||||
* @param integer $category_id Category id
|
||||
* @return bool
|
||||
*/
|
||||
public function remove($category_id)
|
||||
{
|
||||
$this->db->startTransaction();
|
||||
$r1 = $this->db->table(Task::TABLE)->eq('category_id', $category_id)->update(array('category_id' => 0));
|
||||
$r2 = $this->db->table(self::TABLE)->eq('id', $category_id)->remove();
|
||||
$this->db->closeTransaction();
|
||||
|
||||
return $r1 && $r2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate category creation
|
||||
*
|
||||
* @access public
|
||||
* @param array $array Form values
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateCreation(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('project_id', t('The project id is required')),
|
||||
new Validators\Integer('project_id', t('The project id must be an integer')),
|
||||
new Validators\Required('name', t('The name is required')),
|
||||
new Validators\MaxLength('name', t('The maximum length is %d characters', 50), 50)
|
||||
));
|
||||
|
||||
return array(
|
||||
$v->execute(),
|
||||
$v->getErrors()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate category modification
|
||||
*
|
||||
* @access public
|
||||
* @param array $array Form values
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateModification(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('id', t('The id is required')),
|
||||
new Validators\Integer('id', t('The id must be an integer')),
|
||||
new Validators\Required('project_id', t('The project id is required')),
|
||||
new Validators\Integer('project_id', t('The project id must be an integer')),
|
||||
new Validators\Required('name', t('The name is required')),
|
||||
new Validators\MaxLength('name', t('The maximum length is %d characters', 50), 50)
|
||||
));
|
||||
|
||||
return array(
|
||||
$v->execute(),
|
||||
$v->getErrors()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,9 @@ require_once __DIR__.'/board.php';
|
|||
require_once __DIR__.'/task.php';
|
||||
require_once __DIR__.'/../events/task_modification.php';
|
||||
|
||||
use \SimpleValidator\Validator;
|
||||
use \SimpleValidator\Validators;
|
||||
use \Event\TaskModification;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
use Event\TaskModification;
|
||||
|
||||
/**
|
||||
* Project model
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace Model;
|
|||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
use \SimpleValidator\Validator;
|
||||
use \SimpleValidator\Validators;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
|
|
@ -42,6 +42,7 @@ class Task extends Base
|
|||
const EVENT_CREATE = 'task.create';
|
||||
const EVENT_CLOSE = 'task.close';
|
||||
const EVENT_OPEN = 'task.open';
|
||||
const EVENT_CREATE_UPDATE = 'task.create_update';
|
||||
|
||||
/**
|
||||
* Get available colors
|
||||
|
|
@ -90,10 +91,13 @@ class Task extends Base
|
|||
self::TABLE.'.position',
|
||||
self::TABLE.'.is_active',
|
||||
self::TABLE.'.score',
|
||||
self::TABLE.'.category_id',
|
||||
Category::TABLE.'.name AS category_name',
|
||||
Project::TABLE.'.name AS project_name',
|
||||
Board::TABLE.'.title AS column_title',
|
||||
User::TABLE.'.username'
|
||||
)
|
||||
->join(Category::TABLE, 'id', 'category_id')
|
||||
->join(Project::TABLE, 'id', 'project_id')
|
||||
->join(Board::TABLE, 'id', 'column_id')
|
||||
->join(User::TABLE, 'id', 'owner_id')
|
||||
|
|
@ -150,6 +154,7 @@ class Task extends Base
|
|||
'tasks.position',
|
||||
'tasks.is_active',
|
||||
'tasks.score',
|
||||
'tasks.category_id',
|
||||
'users.username'
|
||||
)
|
||||
->join('users', 'id', 'owner_id');
|
||||
|
|
@ -236,6 +241,7 @@ class Task extends Base
|
|||
$this->db->closeTransaction();
|
||||
|
||||
// Trigger events
|
||||
$this->event->trigger(self::EVENT_CREATE_UPDATE, array('task_id' => $task_id) + $task);
|
||||
$this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id) + $task);
|
||||
|
||||
return $task_id;
|
||||
|
|
@ -265,6 +271,7 @@ class Task extends Base
|
|||
// Assign new values
|
||||
$task['date_creation'] = time();
|
||||
$task['owner_id'] = 0;
|
||||
$task['category_id'] = 0;
|
||||
$task['is_active'] = 1;
|
||||
$task['column_id'] = $boardModel->getFirstColumn($project_id);
|
||||
$task['project_id'] = $project_id;
|
||||
|
|
@ -281,6 +288,7 @@ class Task extends Base
|
|||
$this->db->closeTransaction();
|
||||
|
||||
// Trigger events
|
||||
$this->event->trigger(self::EVENT_CREATE_UPDATE, array('task_id' => $task_id) + $task);
|
||||
$this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id) + $task);
|
||||
|
||||
return $task_id;
|
||||
|
|
@ -320,6 +328,7 @@ class Task extends Base
|
|||
$this->db->closeTransaction();
|
||||
|
||||
// Trigger events
|
||||
$this->event->trigger(self::EVENT_CREATE_UPDATE, array('task_id' => $task_id) + $values);
|
||||
$this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id) + $values);
|
||||
|
||||
return $task_id;
|
||||
|
|
@ -355,7 +364,8 @@ class Task extends Base
|
|||
|
||||
$events = array();
|
||||
|
||||
if ($this->event->getLastTriggeredEvent() !== self::EVENT_UPDATE) {
|
||||
if (! in_array($this->event->getLastTriggeredEvent(), array(self::EVENT_CREATE_UPDATE))) {
|
||||
$events[] = self::EVENT_CREATE_UPDATE;
|
||||
$events[] = self::EVENT_UPDATE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,22 @@
|
|||
|
||||
namespace Schema;
|
||||
|
||||
function version_16($pdo)
|
||||
{
|
||||
$pdo->exec("
|
||||
CREATE TABLE project_has_categories (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(255),
|
||||
project_id INT,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY `idx_project_category` (project_id, name),
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB CHARSET=utf8"
|
||||
);
|
||||
|
||||
$pdo->exec("ALTER TABLE tasks ADD COLUMN category_id INT DEFAULT 0");
|
||||
}
|
||||
|
||||
function version_15($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE projects ADD COLUMN last_modified INT DEFAULT 0");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,21 @@
|
|||
|
||||
namespace Schema;
|
||||
|
||||
function version_16($pdo)
|
||||
{
|
||||
$pdo->exec("
|
||||
CREATE TABLE project_has_categories (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT COLLATE NOCASE,
|
||||
project_id INT,
|
||||
UNIQUE (project_id, name),
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||
)"
|
||||
);
|
||||
|
||||
$pdo->exec("ALTER TABLE tasks ADD COLUMN category_id INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
function version_15($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE projects ADD COLUMN last_modified INTEGER DEFAULT 0");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
<?= Helper\in_list($param['value'], $projects_list) ?>
|
||||
<?php elseif (Helper\contains($param['name'], 'color_id')): ?>
|
||||
<?= Helper\in_list($param['value'], $colors_list) ?>
|
||||
<?php elseif (Helper\contains($param['name'], 'category_id')): ?>
|
||||
<?= Helper\in_list($param['value'], $categories_list) ?>
|
||||
<?php endif ?>
|
||||
</strong>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
<?php elseif (Helper\contains($param_name, 'color_id')): ?>
|
||||
<?= Helper\form_label($param_desc, $param_name) ?>
|
||||
<?= Helper\form_select('params['.$param_name.']', $colors_list, $values) ?><br/>
|
||||
<?php elseif (Helper\contains($param_name, 'category_id')): ?>
|
||||
<?= Helper\form_label($param_desc, $param_name) ?>
|
||||
<?= Helper\form_select('params['.$param_name.']', $categories_list, $values) ?><br/>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
<?= t('Filter by user') ?>
|
||||
<?= Helper\form_select('user_id', $users, $filters) ?>
|
||||
</li>
|
||||
<li>
|
||||
<?= t('Filter by category') ?>
|
||||
<?= Helper\form_select('category_id', $categories, $filters) ?>
|
||||
</li>
|
||||
<li><a href="#" id="filter-due-date"><?= t('Filter by due date') ?></a></li>
|
||||
<li><a href="?controller=project&action=search&project_id=<?= $current_project_id ?>"><?= t('Search') ?></a></li>
|
||||
<li><a href="?controller=project&action=tasks&project_id=<?= $current_project_id ?>"><?= t('Completed tasks') ?></a></li>
|
||||
|
|
@ -30,7 +34,7 @@
|
|||
<?php if (empty($board)): ?>
|
||||
<p class="alert alert-error"><?= t('There is no column in your project!') ?></p>
|
||||
<?php else: ?>
|
||||
<?= Helper\template('board_show', array('current_project_id' => $current_project_id, 'board' => $board)) ?>
|
||||
<?= Helper\template('board_show', array('current_project_id' => $current_project_id, 'board' => $board, 'categories' => $categories)) ?>
|
||||
<?php endif ?>
|
||||
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,17 @@
|
|||
<?= 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']) ?>
|
||||
|
|
@ -56,6 +66,7 @@
|
|||
<?php endif ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
<div class="task 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') ?>">
|
||||
|
||||
|
|
@ -50,7 +51,17 @@
|
|||
<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_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']) ?>
|
||||
|
|
@ -67,6 +78,8 @@
|
|||
<?php endif ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<section id="main">
|
||||
<div class="page-header">
|
||||
<h2><?= t('Category modification for the project "%s"', $project['name']) ?></h2>
|
||||
<ul>
|
||||
<li><a href="?controller=project"><?= t('All projects') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<section>
|
||||
|
||||
<form method="post" action="?controller=category&action=update&project_id=<?= $project['id'] ?>" autocomplete="off">
|
||||
|
||||
<?= Helper\form_hidden('id', $values) ?>
|
||||
<?= Helper\form_hidden('project_id', $values) ?>
|
||||
|
||||
<?= Helper\form_label(t('Category Name'), 'name') ?>
|
||||
<?= Helper\form_text('name', $values, $errors, array('required')) ?>
|
||||
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<section id="main">
|
||||
<div class="page-header">
|
||||
<h2><?= t('Categories for the project "%s"', $project['name']) ?></h2>
|
||||
<ul>
|
||||
<li><a href="?controller=project"><?= t('All projects') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<section>
|
||||
|
||||
<?php if (! empty($categories)): ?>
|
||||
<table>
|
||||
<tr>
|
||||
<th><?= t('Category Name') ?></th>
|
||||
<th><?= t('Actions') ?></th>
|
||||
</tr>
|
||||
<?php foreach ($categories as $category_id => $category_name): ?>
|
||||
<tr>
|
||||
<td><?= Helper\escape($category_name) ?></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="?controller=category&action=edit&project_id=<?= $project['id'] ?>&category_id=<?= $category_id ?>"><?= t('Edit') ?></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?controller=category&action=confirm&project_id=<?= $project['id'] ?>&category_id=<?= $category_id ?>"><?= t('Remove') ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
<?php endif ?>
|
||||
|
||||
<h3><?= t('Add a new category') ?></h3>
|
||||
<form method="post" action="?controller=category&action=save&project_id=<?= $project['id'] ?>" autocomplete="off">
|
||||
|
||||
<?= Helper\form_hidden('project_id', $values) ?>
|
||||
|
||||
<?= Helper\form_label(t('Category Name'), 'name') ?>
|
||||
<?= Helper\form_text('name', $values, $errors, array('required')) ?>
|
||||
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<section id="main">
|
||||
<div class="page-header">
|
||||
<h2><?= t('Remove a category') ?></h2>
|
||||
</div>
|
||||
|
||||
<div class="confirm">
|
||||
<p class="alert alert-info">
|
||||
<?= t('Do you really want to remove this category: "%s"?', $category['name']) ?>
|
||||
</p>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="?controller=category&action=remove&project_id=<?= $project['id'] ?>&category_id=<?= $category['id'] ?>" class="btn btn-red"><?= t('Yes') ?></a>
|
||||
<?= t('or') ?> <a href="?controller=category&project_id=<?= $project['id'] ?>"><?= t('cancel') ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -59,6 +59,9 @@
|
|||
<?php if (Helper\is_admin()): ?>
|
||||
<td>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="?controller=category&action=index&project_id=<?= $project['id'] ?>"><?= t('Categories') ?></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?controller=project&action=edit&project_id=<?= $project['id'] ?>"><?= t('Edit project') ?></a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
<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>
|
||||
|
|
@ -43,6 +44,9 @@
|
|||
<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">
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<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>
|
||||
|
|
@ -29,6 +30,9 @@
|
|||
<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">
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@
|
|||
<?= Helper\form_label(t('Assignee'), 'owner_id') ?>
|
||||
<?= Helper\form_select('owner_id', $users_list, $values, $errors) ?><br/>
|
||||
|
||||
<?= Helper\form_label(t('Category'), 'category_id') ?>
|
||||
<?= Helper\form_select('category_id', $categories_list, $values, $errors) ?><br/>
|
||||
|
||||
<?= Helper\form_label(t('Column'), 'column_id') ?>
|
||||
<?= Helper\form_select('column_id', $columns_list, $values, $errors) ?><br/>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
<?= Helper\form_label(t('Assignee'), 'owner_id') ?>
|
||||
<?= Helper\form_select('owner_id', $users_list, $values, $errors) ?><br/>
|
||||
|
||||
<?= Helper\form_label(t('Category'), 'category_id') ?>
|
||||
<?= Helper\form_select('category_id', $categories_list, $values, $errors) ?><br/>
|
||||
|
||||
<?= Helper\form_label(t('Column'), 'column_id') ?>
|
||||
<?= Helper\form_select('column_id', $columns_list, $values, $errors) ?><br/>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
<strong><?= Helper\escape($task['column_title']) ?></strong>
|
||||
(<?= Helper\escape($task['project_name']) ?>)
|
||||
</li>
|
||||
<?php if ($task['category_name']): ?>
|
||||
<li>
|
||||
<?= t('Category:') ?> <strong><?= Helper\escape($task['category_name']) ?></strong>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li>
|
||||
<?php if ($task['is_active'] == 1): ?>
|
||||
<?= t('Status is open') ?>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ abstract class Base extends PHPUnit_Framework_TestCase
|
|||
'filename' => ':memory:'
|
||||
));
|
||||
|
||||
if ($db->schema()->check(10)) {
|
||||
if ($db->schema()->check(16)) {
|
||||
return $db;
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class TaskTest extends Base
|
|||
$this->assertEquals(2, $t->create(array('title' => 'test b', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 2, 'description' => 'toto et titi sont dans un bateau')));
|
||||
|
||||
$tasks = $t->find(array(array('column' => 'project_id', 'operator' => 'eq', 'value' => '1')));
|
||||
$this->assertNotFalse($tasks);
|
||||
$this->assertEquals(2, count($tasks));
|
||||
$this->assertEquals(1, $tasks[0]['id']);
|
||||
$this->assertEquals(2, $tasks[1]['id']);
|
||||
|
|
@ -101,7 +102,7 @@ class TaskTest extends Base
|
|||
|
||||
// We create a task and a project
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1, 'category_id' => 2)));
|
||||
|
||||
$task = $t->getById(1);
|
||||
$this->assertNotEmpty($task);
|
||||
|
|
@ -118,6 +119,7 @@ class TaskTest extends Base
|
|||
$this->assertEquals(1, $task['project_id']);
|
||||
$this->assertEquals(1, $task['owner_id']);
|
||||
$this->assertEquals(1, $task['position']);
|
||||
$this->assertEquals(2, $task['category_id']);
|
||||
}
|
||||
|
||||
public function testDuplicateToAnotherProject()
|
||||
|
|
@ -130,11 +132,19 @@ class TaskTest extends Base
|
|||
$this->assertEquals(2, $p->create(array('name' => 'test2')));
|
||||
|
||||
// We create a task
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1, 'category_id' => 1)));
|
||||
|
||||
// We duplicate our task to the 2nd project
|
||||
$this->assertEquals(2, $t->duplicateToAnotherProject(1, 2));
|
||||
$this->assertEquals(Task::EVENT_CREATE, $this->event->getLastTriggeredEvent());
|
||||
|
||||
// Check the values of the duplicated task
|
||||
$task = $t->getById(2);
|
||||
$this->assertNotEmpty($task);
|
||||
$this->assertEquals(0, $task['owner_id']);
|
||||
$this->assertEquals(0, $task['category_id']);
|
||||
$this->assertEquals(2, $task['project_id']);
|
||||
$this->assertEquals('test', $task['title']);
|
||||
}
|
||||
|
||||
public function testEvents()
|
||||
|
|
|
|||
Loading…
Reference in New Issue