Add the possiblity to reorder the column position for a board
This commit is contained in:
parent
395a8a5f2a
commit
e0a5045ed5
|
|
@ -145,7 +145,7 @@ textarea:focus {
|
|||
}
|
||||
|
||||
input[type="number"] {
|
||||
width: 50px;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,49 @@ namespace Controller;
|
|||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
/**
|
||||
* Board controller
|
||||
*
|
||||
* @package controller
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Board extends Base
|
||||
{
|
||||
// Change a task assignee directly from the board
|
||||
/**
|
||||
* Move a column up
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function moveUp()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
$column_id = $this->request->getIntegerParam('column_id');
|
||||
|
||||
$this->board->moveUp($project_id, $column_id);
|
||||
|
||||
$this->response->redirect('?controller=board&action=edit&project_id='.$project_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a column down
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function moveDown()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
$column_id = $this->request->getIntegerParam('column_id');
|
||||
|
||||
$this->board->moveDown($project_id, $column_id);
|
||||
|
||||
$this->response->redirect('?controller=board&action=edit&project_id='.$project_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a task assignee directly from the board
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function assign()
|
||||
{
|
||||
$task = $this->task->getById($this->request->getIntegerParam('task_id'));
|
||||
|
|
@ -32,7 +72,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Validate an assignee change
|
||||
/**
|
||||
* Validate an assignee modification
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function assignTask()
|
||||
{
|
||||
$values = $this->request->getValues();
|
||||
|
|
@ -50,8 +94,12 @@ class Board extends Base
|
|||
$this->response->redirect('?controller=board&action=show&project_id='.$values['project_id']);
|
||||
}
|
||||
|
||||
// Display the public version of a board
|
||||
// Access checked by a simple token, no user login, read only, auto-refresh
|
||||
/**
|
||||
* Display the public version of a board
|
||||
* Access checked by a simple token, no user login, read only, auto-refresh
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function readonly()
|
||||
{
|
||||
$token = $this->request->getStringParam('token');
|
||||
|
|
@ -72,7 +120,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Display the default user project or the first project
|
||||
/**
|
||||
* Display the default user project or the first project
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$projects = $this->project->getListByStatus(\Model\Project::ACTIVE);
|
||||
|
|
@ -110,7 +162,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Show a board for a given project
|
||||
/**
|
||||
* Show a board for a given project
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
$projects = $this->project->getListByStatus(\Model\Project::ACTIVE);
|
||||
|
|
@ -136,7 +192,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Display a form to edit a board
|
||||
/**
|
||||
* Display a form to edit a board
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
|
|
@ -162,7 +222,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Validate and update a board
|
||||
/**
|
||||
* Validate and update a board
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
|
|
@ -203,7 +267,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Validate and add a new column
|
||||
/**
|
||||
* Validate and add a new column
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
|
|
@ -242,7 +310,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Confirmation dialog before removing a column
|
||||
/**
|
||||
* Confirmation dialog before removing a column
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function confirm()
|
||||
{
|
||||
$this->response->html($this->template->layout('board_remove', array(
|
||||
|
|
@ -252,7 +324,11 @@ class Board extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
// Remove a column
|
||||
/**
|
||||
* Remove a column
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
$column = $this->board->getColumn($this->request->getIntegerParam('column_id'));
|
||||
|
|
@ -266,7 +342,11 @@ class Board extends Base
|
|||
$this->response->redirect('?controller=board&action=edit&project_id='.$column['project_id']);
|
||||
}
|
||||
|
||||
// Save the board (Ajax request made by the drag and drop)
|
||||
/**
|
||||
* Save the board (Ajax request made by the drag and drop)
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$project_id = $this->request->getIntegerParam('project_id');
|
||||
|
|
|
|||
|
|
@ -248,4 +248,8 @@ return array(
|
|||
'Open a closed task' => 'Ouverture d\'une tâche fermée',
|
||||
'Closing a task' => 'Fermeture d\'une tâche',
|
||||
'Assign a color to a specific user' => 'Assigner une couleur à un utilisateur',
|
||||
'Column title' => 'Titre de la colonne',
|
||||
'Position' => 'Position',
|
||||
'Move Up' => 'Déplacer vers le haut',
|
||||
'Move Down' => 'Déplacer vers le bas',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ return array(
|
|||
'The description is required' => 'Opis jest wymagany',
|
||||
'Edit this task' => 'Edytuj zadanie',
|
||||
'Due Date' => 'Termin',
|
||||
'm/d/Y' => 'd/m/Y', // Date format parsed with php
|
||||
'm/d/Y' => 'd/m/Y', // Date format parsed with php
|
||||
'month/day/year' => 'dzień/miesiąc/rok', // Help shown to the user
|
||||
'Invalid date' => 'Błędna data',
|
||||
'Must be done before %B %e, %G' => 'Termin do %e %B %G',
|
||||
|
|
@ -251,4 +251,8 @@ return array(
|
|||
'Open a closed task' => 'Otwarcie zamkniętego zadania',
|
||||
'Closing a task' => 'Zamknięcie zadania',
|
||||
'Assign a color to a specific user' => 'Przypisz kolor do wybranego użytkownika',
|
||||
// 'Column title' => '',
|
||||
// 'Position' => '',
|
||||
// 'Move Up' => '',
|
||||
// 'Move Down' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ require_once __DIR__.'/task.php';
|
|||
use \SimpleValidator\Validator;
|
||||
use \SimpleValidator\Validators;
|
||||
|
||||
/**
|
||||
* Action model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Action extends Base
|
||||
{
|
||||
const TABLE = 'actions';
|
||||
|
|
|
|||
182
models/board.php
182
models/board.php
|
|
@ -8,11 +8,23 @@ require_once __DIR__.'/task.php';
|
|||
use \SimpleValidator\Validator;
|
||||
use \SimpleValidator\Validators;
|
||||
|
||||
/**
|
||||
* Board model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Board extends Base
|
||||
{
|
||||
const TABLE = 'columns';
|
||||
|
||||
// Save the board (each task position/column)
|
||||
/**
|
||||
* Save task positions for each column
|
||||
*
|
||||
* @access public
|
||||
* @param array $values [['task_id' => X, 'column_id' => X, 'position' => X], ...]
|
||||
* @return boolean
|
||||
*/
|
||||
public function saveTasksPosition(array $values)
|
||||
{
|
||||
$this->db->startTransaction();
|
||||
|
|
@ -33,7 +45,14 @@ class Board extends Base
|
|||
return ! in_array(false, $results, true);
|
||||
}
|
||||
|
||||
// Create board with default columns => must be executed inside a transaction
|
||||
/**
|
||||
* Create a board with default columns, must be executed inside a transaction
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param array $columns List of columns title ['column1', 'column2', ...]
|
||||
* @return boolean
|
||||
*/
|
||||
public function create($project_id, array $columns)
|
||||
{
|
||||
$position = 0;
|
||||
|
|
@ -46,20 +65,34 @@ class Board extends Base
|
|||
'project_id' => $project_id,
|
||||
);
|
||||
|
||||
$this->db->table(self::TABLE)->save($values);
|
||||
if (! $this->db->table(self::TABLE)->save($values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add a new column to the board
|
||||
/**
|
||||
* Add a new column to the board
|
||||
*
|
||||
* @access public
|
||||
* @param array $values ['title' => X, 'project_id' => X]
|
||||
* @return boolean
|
||||
*/
|
||||
public function add(array $values)
|
||||
{
|
||||
$values['position'] = $this->getLastColumnPosition($values['project_id']) + 1;
|
||||
return $this->db->table(self::TABLE)->save($values);
|
||||
}
|
||||
|
||||
// Update columns
|
||||
/**
|
||||
* Update columns
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(array $values)
|
||||
{
|
||||
$this->db->startTransaction();
|
||||
|
|
@ -75,7 +108,71 @@ class Board extends Base
|
|||
return true;
|
||||
}
|
||||
|
||||
// Get columns and tasks for each column
|
||||
/**
|
||||
* Move a column down, increment the column position value
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $column_id Column id
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveDown($project_id, $column_id)
|
||||
{
|
||||
$columns = $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->listing('id', 'position');
|
||||
$positions = array_flip($columns);
|
||||
|
||||
if (isset($columns[$column_id]) && $columns[$column_id] < count($columns)) {
|
||||
|
||||
$position = ++$columns[$column_id];
|
||||
$columns[$positions[$position]]--;
|
||||
|
||||
$this->db->startTransaction();
|
||||
$this->db->table(self::TABLE)->eq('id', $column_id)->update(array('position' => $position));
|
||||
$this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $columns[$positions[$position]]));
|
||||
$this->db->closeTransaction();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a column up, decrement the column position value
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $column_id Column id
|
||||
* @return boolean
|
||||
*/
|
||||
public function moveUp($project_id, $column_id)
|
||||
{
|
||||
$columns = $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->listing('id', 'position');
|
||||
$positions = array_flip($columns);
|
||||
|
||||
if (isset($columns[$column_id]) && $columns[$column_id] > 1) {
|
||||
|
||||
$position = --$columns[$column_id];
|
||||
$columns[$positions[$position]]++;
|
||||
|
||||
$this->db->startTransaction();
|
||||
$this->db->table(self::TABLE)->eq('id', $column_id)->update(array('position' => $position));
|
||||
$this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $columns[$positions[$position]]));
|
||||
$this->db->closeTransaction();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all columns and tasks for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return array
|
||||
*/
|
||||
public function get($project_id)
|
||||
{
|
||||
$this->db->startTransaction();
|
||||
|
|
@ -92,37 +189,73 @@ class Board extends Base
|
|||
return $columns;
|
||||
}
|
||||
|
||||
// Get first column id for a given project
|
||||
/**
|
||||
* Get the first column id for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return integer
|
||||
*/
|
||||
public function getFirstColumn($project_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findOneColumn('id');
|
||||
}
|
||||
|
||||
// Get list of columns
|
||||
/**
|
||||
* Get the list of columns sorted by position [ column_id => title ]
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsList($project_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->listing('id', 'title');
|
||||
}
|
||||
|
||||
// Get all columns information for a project
|
||||
/**
|
||||
* Get all columns sorted by position for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns($project_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findAll();
|
||||
}
|
||||
|
||||
// Get the number of columns for a project
|
||||
/**
|
||||
* Get the number of columns for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return integer
|
||||
*/
|
||||
public function countColumns($project_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->count();
|
||||
}
|
||||
|
||||
// Get just one column
|
||||
/**
|
||||
* Get a column by the id
|
||||
*
|
||||
* @access public
|
||||
* @param integer $column_id Column id
|
||||
* @return array
|
||||
*/
|
||||
public function getColumn($column_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('id', $column_id)->findOne();
|
||||
}
|
||||
|
||||
// Get the position of the last column for a project
|
||||
/**
|
||||
* Get the position of the last column for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return integer
|
||||
*/
|
||||
public function getLastColumnPosition($project_id)
|
||||
{
|
||||
return (int) $this->db
|
||||
|
|
@ -132,13 +265,26 @@ class Board extends Base
|
|||
->findOneColumn('position');
|
||||
}
|
||||
|
||||
// Remove a column and all tasks associated to this column
|
||||
/**
|
||||
* Remove a column and all tasks associated to this column
|
||||
*
|
||||
* @access public
|
||||
* @param integer $column_id Column id
|
||||
* @return boolean
|
||||
*/
|
||||
public function removeColumn($column_id)
|
||||
{
|
||||
return $this->db->table(self::TABLE)->eq('id', $column_id)->remove();
|
||||
}
|
||||
|
||||
// Validate columns update
|
||||
/**
|
||||
* Validate column modification
|
||||
*
|
||||
* @access public
|
||||
* @param array $columns Original columns List
|
||||
* @param array $values Required parameters to update a column
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateModification(array $columns, array $values)
|
||||
{
|
||||
$rules = array();
|
||||
|
|
@ -158,7 +304,13 @@ class Board extends Base
|
|||
);
|
||||
}
|
||||
|
||||
// Validate column creation
|
||||
/**
|
||||
* Validate column creation
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Required parameters to save an action
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateCreation(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
|
|
|
|||
|
|
@ -11,13 +11,38 @@
|
|||
<form method="post" action="?controller=board&action=update&project_id=<?= $project['id'] ?>" autocomplete="off">
|
||||
|
||||
<?php $i = 0; ?>
|
||||
|
||||
<?php foreach ($columns as $column): ?>
|
||||
<?= Helper\form_label(t('Column %d', ++$i), 'title['.$column['id'].']') ?>
|
||||
<?= Helper\form_text('title['.$column['id'].']', $values, $errors, array('required')) ?>
|
||||
<?= Helper\form_number('task_limit['.$column['id'].']', $values, $errors, array('placeholder="'.t('limit').'"')) ?>
|
||||
<a href="?controller=board&action=confirm&project_id=<?= $project['id'] ?>&column_id=<?= $column['id'] ?>"><?= t('Remove') ?></a>
|
||||
<?php endforeach ?>
|
||||
<table>
|
||||
<tr>
|
||||
<th><?= t('Position') ?></th>
|
||||
<th><?= t('Column title') ?></th>
|
||||
<th><?= t('Task limit') ?></th>
|
||||
<th><?= t('Actions') ?></th>
|
||||
</tr>
|
||||
<?php foreach ($columns as $column): ?>
|
||||
<tr>
|
||||
<td><?= Helper\form_label(t('Column %d', ++$i), 'title['.$column['id'].']') ?></td>
|
||||
<td><?= Helper\form_text('title['.$column['id'].']', $values, $errors, array('required')) ?></td>
|
||||
<td><?= Helper\form_number('task_limit['.$column['id'].']', $values, $errors, array('placeholder="'.t('limit').'"')) ?></td>
|
||||
<td>
|
||||
<ul>
|
||||
<?php if ($column['position'] != 1): ?>
|
||||
<li>
|
||||
<a href="?controller=board&action=moveUp&project_id=<?= $project['id'] ?>&column_id=<?= $column['id'] ?>"><?= t('Move Up') ?></a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if ($column['position'] != count($columns)): ?>
|
||||
<li>
|
||||
<a href="?controller=board&action=moveDown&project_id=<?= $project['id'] ?>&column_id=<?= $column['id'] ?>"><?= t('Move Down') ?></a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li>
|
||||
<a href="?controller=board&action=confirm&project_id=<?= $project['id'] ?>&column_id=<?= $column['id'] ?>"><?= t('Remove') ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Update') ?>" class="btn btn-blue"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/base.php';
|
||||
|
||||
use Model\Project;
|
||||
use Model\Board;
|
||||
|
||||
class BoardTest extends Base
|
||||
{
|
||||
public function testMoveColumns()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$b = new Board($this->db, $this->event);
|
||||
|
||||
// We create 2 projects
|
||||
$this->assertEquals(1, $p->create(array('name' => 'UnitTest1')));
|
||||
$this->assertEquals(2, $p->create(array('name' => 'UnitTest2')));
|
||||
|
||||
// We get the columns of the project 2
|
||||
$columns = $b->getColumns(2);
|
||||
$columns_id = array_keys($b->getColumnsList(2));
|
||||
$this->assertNotEmpty($columns);
|
||||
|
||||
// Initial order: 5, 6, 7, 8
|
||||
|
||||
// Move the column 1 down
|
||||
$this->assertEquals(1, $columns[0]['position']);
|
||||
$this->assertEquals($columns_id[0], $columns[0]['id']);
|
||||
|
||||
$this->assertEquals(2, $columns[1]['position']);
|
||||
$this->assertEquals($columns_id[1], $columns[1]['id']);
|
||||
|
||||
$this->assertTrue($b->moveDown(2, $columns[0]['id']));
|
||||
$columns = $b->getColumns(2); // Sorted by position
|
||||
|
||||
// New order: 6, 5, 7, 8
|
||||
|
||||
$this->assertEquals(1, $columns[0]['position']);
|
||||
$this->assertEquals($columns_id[1], $columns[0]['id']);
|
||||
|
||||
$this->assertEquals(2, $columns[1]['position']);
|
||||
$this->assertEquals($columns_id[0], $columns[1]['id']);
|
||||
|
||||
// Move the column 3 up
|
||||
$this->assertTrue($b->moveUp(2, $columns[2]['id']));
|
||||
$columns = $b->getColumns(2);
|
||||
|
||||
// New order: 6, 7, 5, 8
|
||||
|
||||
$this->assertEquals(1, $columns[0]['position']);
|
||||
$this->assertEquals($columns_id[1], $columns[0]['id']);
|
||||
|
||||
$this->assertEquals(2, $columns[1]['position']);
|
||||
$this->assertEquals($columns_id[2], $columns[1]['id']);
|
||||
|
||||
$this->assertEquals(3, $columns[2]['position']);
|
||||
$this->assertEquals($columns_id[0], $columns[2]['id']);
|
||||
|
||||
// Move column 1 up (must do nothing because it's the first column)
|
||||
$this->assertFalse($b->moveUp(2, $columns[0]['id']));
|
||||
$columns = $b->getColumns(2);
|
||||
|
||||
// Order: 6, 7, 5, 8
|
||||
|
||||
$this->assertEquals(1, $columns[0]['position']);
|
||||
$this->assertEquals($columns_id[1], $columns[0]['id']);
|
||||
|
||||
// Move column 4 down (must do nothing because it's the last column)
|
||||
$this->assertFalse($b->moveDown(2, $columns[3]['id']));
|
||||
$columns = $b->getColumns(2);
|
||||
|
||||
// Order: 6, 7, 5, 8
|
||||
|
||||
$this->assertEquals(4, $columns[3]['position']);
|
||||
$this->assertEquals($columns_id[3], $columns[3]['id']);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue