Add option to clone filters on project duplication
* Fixed missing metadata option from project "create from" * Added option to clone project custom filters * Added append option to custom field tests * Added a test that uses the "append" option * Fixed disabled swimlane duplication error with Postgresql
This commit is contained in:
committed by
Frédéric Guillot
parent
d3be738d4f
commit
c250f3b1b8
@@ -101,4 +101,39 @@ class CustomFilterModel extends Base
|
|||||||
{
|
{
|
||||||
return $this->db->table(self::TABLE)->eq('id', $filter_id)->remove();
|
return $this->db->table(self::TABLE)->eq('id', $filter_id)->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate custom filters from a project to another one, must be executed inside a transaction
|
||||||
|
*
|
||||||
|
* @param integer $src_project_id Source project id
|
||||||
|
* @param integer $dst_project_id Destination project id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function duplicate($src_project_id, $dst_project_id)
|
||||||
|
{
|
||||||
|
$filters = $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->columns(
|
||||||
|
self::TABLE.'.user_id',
|
||||||
|
self::TABLE.'.filter',
|
||||||
|
self::TABLE.'.name',
|
||||||
|
self::TABLE.'.is_shared',
|
||||||
|
self::TABLE.'.append'
|
||||||
|
)
|
||||||
|
->eq('project_id', $src_project_id)
|
||||||
|
->findAll();
|
||||||
|
|
||||||
|
foreach ($filters as $filter) {
|
||||||
|
$filter['project_id'] = $dst_project_id;
|
||||||
|
// Avoid SQL error with Postgres
|
||||||
|
$filter['is_shared'] = $filter['is_shared'] ?: 0;
|
||||||
|
$filter['append'] = $filter['append'] ?: 0;
|
||||||
|
|
||||||
|
if (! $this->db->table(self::TABLE)->save($filter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class ProjectDuplicationModel extends Base
|
|||||||
'projectPermissionModel',
|
'projectPermissionModel',
|
||||||
'actionModel',
|
'actionModel',
|
||||||
'tagDuplicationModel',
|
'tagDuplicationModel',
|
||||||
|
'customFilterModel',
|
||||||
'projectMetadataModel',
|
'projectMetadataModel',
|
||||||
'projectTaskDuplicationModel',
|
'projectTaskDuplicationModel',
|
||||||
);
|
);
|
||||||
@@ -50,6 +51,7 @@ class ProjectDuplicationModel extends Base
|
|||||||
'actionModel',
|
'actionModel',
|
||||||
'swimlaneModel',
|
'swimlaneModel',
|
||||||
'tagDuplicationModel',
|
'tagDuplicationModel',
|
||||||
|
'customFilterModel',
|
||||||
'projectMetadataModel',
|
'projectMetadataModel',
|
||||||
'projectTaskDuplicationModel',
|
'projectTaskDuplicationModel',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ class SwimlaneModel extends Base
|
|||||||
'name' => $swimlane['name'],
|
'name' => $swimlane['name'],
|
||||||
'description' => $swimlane['description'],
|
'description' => $swimlane['description'],
|
||||||
'position' => $swimlane['position'],
|
'position' => $swimlane['position'],
|
||||||
'is_active' => $swimlane['is_active'],
|
'is_active' => $swimlane['is_active'] ? self::ACTIVE : self::INACTIVE, // Avoid SQL error with Postgres
|
||||||
'project_id' => $projectDstId,
|
'project_id' => $projectDstId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
<?= $this->form->checkbox('categoryModel', t('Categories'), 1, true) ?>
|
<?= $this->form->checkbox('categoryModel', t('Categories'), 1, true) ?>
|
||||||
<?= $this->form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?>
|
<?= $this->form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?>
|
||||||
<?= $this->form->checkbox('actionModel', t('Actions'), 1, true) ?>
|
<?= $this->form->checkbox('actionModel', t('Actions'), 1, true) ?>
|
||||||
|
<?= $this->form->checkbox('customFilterModel', t('Custom filters'), 1, true) ?>
|
||||||
|
<?= $this->form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?>
|
||||||
<?= $this->form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
|
<?= $this->form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<?= $this->form->checkbox('categoryModel', t('Categories'), 1, true) ?>
|
<?= $this->form->checkbox('categoryModel', t('Categories'), 1, true) ?>
|
||||||
<?= $this->form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?>
|
<?= $this->form->checkbox('tagDuplicationModel', t('Tags'), 1, true) ?>
|
||||||
<?= $this->form->checkbox('actionModel', t('Actions'), 1, true) ?>
|
<?= $this->form->checkbox('actionModel', t('Actions'), 1, true) ?>
|
||||||
|
<?= $this->form->checkbox('customFilterModel', t('Custom filters'), 1, true) ?>
|
||||||
<?= $this->form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?>
|
<?= $this->form->checkbox('projectMetadataModel', t('Metadata'), 1, false) ?>
|
||||||
<?= $this->form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
|
<?= $this->form->checkbox('projectTaskDuplicationModel', t('Tasks'), 1, false) ?>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class CustomFilterTest extends Base
|
|||||||
$this->assertEquals(1, $p->create(array('name' => 'UnitTest')));
|
$this->assertEquals(1, $p->create(array('name' => 'UnitTest')));
|
||||||
$this->assertEquals(1, $cf->create(array('name' => 'My filter 1', 'filter' => 'status:open color:blue', 'project_id' => 1, 'user_id' => 1)));
|
$this->assertEquals(1, $cf->create(array('name' => 'My filter 1', 'filter' => 'status:open color:blue', 'project_id' => 1, 'user_id' => 1)));
|
||||||
$this->assertEquals(2, $cf->create(array('name' => 'My filter 2', 'filter' => 'status:open color:red', 'project_id' => 1, 'user_id' => 1, 'is_shared' => 1)));
|
$this->assertEquals(2, $cf->create(array('name' => 'My filter 2', 'filter' => 'status:open color:red', 'project_id' => 1, 'user_id' => 1, 'is_shared' => 1)));
|
||||||
|
$this->assertEquals(3, $cf->create(array('name' => 'My filter 3', 'filter' => 'status:open color:green', 'project_id' => 1, 'user_id' => 1, 'append' => 1)));
|
||||||
|
|
||||||
$filter = $cf->getById(1);
|
$filter = $cf->getById(1);
|
||||||
$this->assertNotEmpty($filter);
|
$this->assertNotEmpty($filter);
|
||||||
@@ -24,6 +25,7 @@ class CustomFilterTest extends Base
|
|||||||
$this->assertEquals(1, $filter['project_id']);
|
$this->assertEquals(1, $filter['project_id']);
|
||||||
$this->assertEquals(1, $filter['user_id']);
|
$this->assertEquals(1, $filter['user_id']);
|
||||||
$this->assertEquals(0, $filter['is_shared']);
|
$this->assertEquals(0, $filter['is_shared']);
|
||||||
|
$this->assertEquals(0, $filter['append']);
|
||||||
|
|
||||||
$filter = $cf->getById(2);
|
$filter = $cf->getById(2);
|
||||||
$this->assertNotEmpty($filter);
|
$this->assertNotEmpty($filter);
|
||||||
@@ -32,6 +34,16 @@ class CustomFilterTest extends Base
|
|||||||
$this->assertEquals(1, $filter['project_id']);
|
$this->assertEquals(1, $filter['project_id']);
|
||||||
$this->assertEquals(1, $filter['user_id']);
|
$this->assertEquals(1, $filter['user_id']);
|
||||||
$this->assertEquals(1, $filter['is_shared']);
|
$this->assertEquals(1, $filter['is_shared']);
|
||||||
|
$this->assertEquals(0, $filter['append']);
|
||||||
|
|
||||||
|
$filter = $cf->getById(3);
|
||||||
|
$this->assertNotEmpty($filter);
|
||||||
|
$this->assertEquals('My filter 3', $filter['name']);
|
||||||
|
$this->assertEquals('status:open color:green', $filter['filter']);
|
||||||
|
$this->assertEquals(1, $filter['project_id']);
|
||||||
|
$this->assertEquals(1, $filter['user_id']);
|
||||||
|
$this->assertEquals(0, $filter['is_shared']);
|
||||||
|
$this->assertEquals(1, $filter['append']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testModification()
|
public function testModification()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use Kanboard\Model\SwimlaneModel;
|
|||||||
use Kanboard\Model\TaskModel;
|
use Kanboard\Model\TaskModel;
|
||||||
use Kanboard\Model\TaskCreationModel;
|
use Kanboard\Model\TaskCreationModel;
|
||||||
use Kanboard\Model\TaskFinderModel;
|
use Kanboard\Model\TaskFinderModel;
|
||||||
|
use Kanboard\Model\CustomFilterModel;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
class ProjectDuplicationModelTest extends Base
|
class ProjectDuplicationModelTest extends Base
|
||||||
@@ -24,8 +25,8 @@ class ProjectDuplicationModelTest extends Base
|
|||||||
public function testGetSelections()
|
public function testGetSelections()
|
||||||
{
|
{
|
||||||
$projectDuplicationModel = new ProjectDuplicationModel($this->container);
|
$projectDuplicationModel = new ProjectDuplicationModel($this->container);
|
||||||
$this->assertCount(7, $projectDuplicationModel->getOptionalSelection());
|
$this->assertCount(8, $projectDuplicationModel->getOptionalSelection());
|
||||||
$this->assertCount(10, $projectDuplicationModel->getPossibleSelection());
|
$this->assertCount(11, $projectDuplicationModel->getPossibleSelection());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetClonedProjectName()
|
public function testGetClonedProjectName()
|
||||||
@@ -539,6 +540,9 @@ class ProjectDuplicationModelTest extends Base
|
|||||||
$this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1)));
|
$this->assertEquals(2, $taskCreationModel->create(array('title' => 'T2', 'project_id' => 1, 'column_id' => 2, 'owner_id' => 1)));
|
||||||
$this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
$this->assertEquals(3, $taskCreationModel->create(array('title' => 'T3', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
||||||
|
|
||||||
|
// make the first swimlane inactive (keep positions)
|
||||||
|
$this->assertTrue($swimlaneModel->disable(1, 1));
|
||||||
|
|
||||||
$this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'projectTaskDuplicationModel')));
|
$this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('projectPermissionModel', 'swimlaneModel', 'projectTaskDuplicationModel')));
|
||||||
|
|
||||||
// Check if Swimlanes have been duplicated
|
// Check if Swimlanes have been duplicated
|
||||||
@@ -546,12 +550,16 @@ class ProjectDuplicationModelTest extends Base
|
|||||||
$this->assertCount(4, $swimlanes);
|
$this->assertCount(4, $swimlanes);
|
||||||
$this->assertEquals(5, $swimlanes[0]['id']);
|
$this->assertEquals(5, $swimlanes[0]['id']);
|
||||||
$this->assertEquals('Default swimlane', $swimlanes[0]['name']);
|
$this->assertEquals('Default swimlane', $swimlanes[0]['name']);
|
||||||
|
$this->assertEquals(0, $swimlanes[0]['is_active']);
|
||||||
$this->assertEquals(6, $swimlanes[1]['id']);
|
$this->assertEquals(6, $swimlanes[1]['id']);
|
||||||
$this->assertEquals('S1', $swimlanes[1]['name']);
|
$this->assertEquals('S1', $swimlanes[1]['name']);
|
||||||
|
$this->assertEquals(1, $swimlanes[1]['is_active']);
|
||||||
$this->assertEquals(7, $swimlanes[2]['id']);
|
$this->assertEquals(7, $swimlanes[2]['id']);
|
||||||
$this->assertEquals('S2', $swimlanes[2]['name']);
|
$this->assertEquals('S2', $swimlanes[2]['name']);
|
||||||
|
$this->assertEquals(1, $swimlanes[2]['is_active']);
|
||||||
$this->assertEquals(8, $swimlanes[3]['id']);
|
$this->assertEquals(8, $swimlanes[3]['id']);
|
||||||
$this->assertEquals('S3', $swimlanes[3]['name']);
|
$this->assertEquals('S3', $swimlanes[3]['name']);
|
||||||
|
$this->assertEquals(1, $swimlanes[3]['is_active']);
|
||||||
|
|
||||||
// Check if Tasks have been duplicated
|
// Check if Tasks have been duplicated
|
||||||
$tasks = $taskFinderModel->getAll(2);
|
$tasks = $taskFinderModel->getAll(2);
|
||||||
@@ -603,4 +611,36 @@ class ProjectDuplicationModelTest extends Base
|
|||||||
$tags = $taskTagModel->getList(6);
|
$tags = $taskTagModel->getList(6);
|
||||||
$this->assertEquals('C', $tags[6]);
|
$this->assertEquals('C', $tags[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCloneProjectWithCustomFilters()
|
||||||
|
{
|
||||||
|
$projectModel = new ProjectModel($this->container);
|
||||||
|
$customFilterModel = new CustomFilterModel($this->container);
|
||||||
|
$projectDuplicationModel = new ProjectDuplicationModel($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'P1')));
|
||||||
|
|
||||||
|
$this->assertEquals(1, $customFilterModel->create(array('name' => 'My filter 1', 'filter' => 'status:open color:blue', 'project_id' => 1, 'user_id' => 1, 'append' => 1)));
|
||||||
|
$this->assertEquals(2, $customFilterModel->create(array('name' => 'My filter 2', 'filter' => 'status:open color:red', 'project_id' => 1, 'user_id' => 1, 'is_shared' => 1)));
|
||||||
|
|
||||||
|
$this->assertEquals(2, $projectDuplicationModel->duplicate(1, array('customFilterModel')));
|
||||||
|
|
||||||
|
$filter = $customFilterModel->getById(3);
|
||||||
|
$this->assertNotEmpty($filter);
|
||||||
|
$this->assertEquals('My filter 1', $filter['name']);
|
||||||
|
$this->assertEquals('status:open color:blue', $filter['filter']);
|
||||||
|
$this->assertEquals(2, $filter['project_id']);
|
||||||
|
$this->assertEquals(1, $filter['user_id']);
|
||||||
|
$this->assertEquals(0, $filter['is_shared']);
|
||||||
|
$this->assertEquals(1, $filter['append']);
|
||||||
|
|
||||||
|
$filter = $customFilterModel->getById(4);
|
||||||
|
$this->assertNotEmpty($filter);
|
||||||
|
$this->assertEquals('My filter 2', $filter['name']);
|
||||||
|
$this->assertEquals('status:open color:red', $filter['filter']);
|
||||||
|
$this->assertEquals(2, $filter['project_id']);
|
||||||
|
$this->assertEquals(1, $filter['user_id']);
|
||||||
|
$this->assertEquals(1, $filter['is_shared']);
|
||||||
|
$this->assertEquals(0, $filter['append']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user