"Add dependencies" implemented
A few bugs in the SQL scripts have been fixed. It is now possible to add new dependencies to a task from the details page.
This commit is contained in:
parent
60d4fe1199
commit
ba3fcc2470
8 changed files with 161 additions and 4 deletions
|
@ -22,6 +22,7 @@ GRANT SELECT,UPDATE ON notes_note_id_seq TO :webapp_user;
|
||||||
CREATE SEQUENCE task_dependencies_taskdep_id_seq INCREMENT 1
|
CREATE SEQUENCE task_dependencies_taskdep_id_seq INCREMENT 1
|
||||||
MINVALUE 1 MAXVALUE 9223372036854775807
|
MINVALUE 1 MAXVALUE 9223372036854775807
|
||||||
START 1 CACHE 1;
|
START 1 CACHE 1;
|
||||||
|
GRANT SELECT,UPDATE ON task_dependencies_taskdep_id_seq TO :webapp_user;
|
||||||
|
|
||||||
-- Tables
|
-- Tables
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,7 @@ CREATE OR REPLACE FUNCTION tasks_add_dependency( t_id INT , t_dependency INT )
|
||||||
SECURITY INVOKER
|
SECURITY INVOKER
|
||||||
AS $tasks_add_dependency$
|
AS $tasks_add_dependency$
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO task_dependencies( task_id , task_id_depends_on )
|
INSERT INTO task_dependencies( task_id , task_id_depends )
|
||||||
VALUES ( t_id , t_dependency );
|
VALUES ( t_id , t_dependency );
|
||||||
RETURN 0;
|
RETURN 0;
|
||||||
EXCEPTION
|
EXCEPTION
|
||||||
|
|
|
@ -57,7 +57,7 @@ class DAO_Items
|
||||||
public function getLineage( Data_Item $item )
|
public function getLineage( Data_Item $item )
|
||||||
{
|
{
|
||||||
if ( is_array( $item->lineage ) ) {
|
if ( is_array( $item->lineage ) ) {
|
||||||
return;
|
return $item->lineage;
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $this->query(
|
$query = $this->query(
|
||||||
|
@ -80,6 +80,7 @@ class DAO_Items
|
||||||
array_push( $stack , $entry->item_id );
|
array_push( $stack , $entry->item_id );
|
||||||
}
|
}
|
||||||
$item->lineage = $stack;
|
$item->lineage = $stack;
|
||||||
|
return $item->lineage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ class DAO_Tasks
|
||||||
. 'INNER JOIN items i USING ( item_id ) '
|
. 'INNER JOIN items i USING ( item_id ) '
|
||||||
. 'LEFT OUTER JOIN completed_tasks ct ON ct.task_id = t.task_id '
|
. 'LEFT OUTER JOIN completed_tasks ct ON ct.task_id = t.task_id '
|
||||||
. 'WHERE td.task_id = $1 '
|
. 'WHERE td.task_id = $1 '
|
||||||
. 'ORDER BY i.item_name , t.task_priority , t.task_title' )->execute( $id );
|
. 'ORDER BY i.item_name , t.task_priority DESC , t.task_title' )->execute( $id );
|
||||||
$task->reverseDependencies = $this->query(
|
$task->reverseDependencies = $this->query(
|
||||||
'SELECT t.task_id AS id , t.task_title AS title , t.item_id AS item , '
|
'SELECT t.task_id AS id , t.task_title AS title , t.item_id AS item , '
|
||||||
. 'i.item_name AS item_name , '
|
. 'i.item_name AS item_name , '
|
||||||
|
@ -117,6 +117,12 @@ class DAO_Tasks
|
||||||
. 'INNER JOIN items i USING ( item_id ) '
|
. 'INNER JOIN items i USING ( item_id ) '
|
||||||
. 'LEFT OUTER JOIN completed_tasks ct USING ( task_id ) '
|
. 'LEFT OUTER JOIN completed_tasks ct USING ( task_id ) '
|
||||||
. 'WHERE td.task_id_depends = $1 '
|
. 'WHERE td.task_id_depends = $1 '
|
||||||
|
. 'ORDER BY i.item_name , t.task_priority DESC , t.task_title' )->execute( $id );
|
||||||
|
$task->possibleDependencies = $this->query(
|
||||||
|
'SELECT t.task_id AS id , t.task_title AS title , t.item_id AS item , '
|
||||||
|
. 'i.item_name AS item_name '
|
||||||
|
. 'FROM tasks_possible_dependencies( $1 ) t '
|
||||||
|
. 'INNER JOIN items i USING ( item_id ) '
|
||||||
. 'ORDER BY i.item_name , t.task_priority , t.task_title' )->execute( $id );
|
. 'ORDER BY i.item_name , t.task_priority , t.task_title' )->execute( $id );
|
||||||
|
|
||||||
return $task;
|
return $task;
|
||||||
|
@ -218,4 +224,11 @@ class DAO_Tasks
|
||||||
->execute( $id , $text );
|
->execute( $id , $text );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addDependency( $id , $dependency )
|
||||||
|
{
|
||||||
|
$result = $this->query( 'SELECT tasks_add_dependency( $1 , $2 ) AS error' )
|
||||||
|
->execute( $id , $dependency );
|
||||||
|
return $result[0]->error;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,10 +107,15 @@ class Ctrl_TaskDependencies
|
||||||
public function handle( Page $page )
|
public function handle( Page $page )
|
||||||
{
|
{
|
||||||
$views = array(
|
$views = array(
|
||||||
Loader::View( 'box' , 'Dependencies' ,
|
$depBox = Loader::View( 'box' , 'Dependencies' ,
|
||||||
Loader::View( 'task_dependencies' , $this->task , false ) )
|
Loader::View( 'task_dependencies' , $this->task , false ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( ! empty( $this->task->possibleDependencies ) ) {
|
||||||
|
$depBox->addButton( BoxButton::create( 'Add dependency' , 'tasks/deps/add?to=' . $this->task->id )
|
||||||
|
->setClass( 'list-add' ) );
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! empty( $this->task->reverseDependencies ) ) {
|
if ( ! empty( $this->task->reverseDependencies ) ) {
|
||||||
array_push( $views , Loader::View( 'box' , 'Reverse dependencies' ,
|
array_push( $views , Loader::View( 'box' , 'Reverse dependencies' ,
|
||||||
Loader::View( 'task_dependencies' , $this->task , true ) ) );
|
Loader::View( 'task_dependencies' , $this->task , true ) ) );
|
||||||
|
@ -340,3 +345,43 @@ class Ctrl_EditNote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Ctrl_DependencyAdd
|
||||||
|
extends Controller
|
||||||
|
implements FormAware
|
||||||
|
{
|
||||||
|
private $form;
|
||||||
|
|
||||||
|
public function setForm( Form $form )
|
||||||
|
{
|
||||||
|
$this->form = $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle( Page $page )
|
||||||
|
{
|
||||||
|
$id = (int) $this->form->field( 'to' )->value( );
|
||||||
|
$dependency = $this->form->field( 'dependency' )->value( );
|
||||||
|
$error = Loader::DAO( 'tasks' )->addDependency( $id , $dependency );
|
||||||
|
|
||||||
|
switch ( $error ) {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
$name->putError( 'The task you selected has been deleted.' );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
$item->putError( 'This dependency is no longer possible.' );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$name->putError( "An unknown error occurred ($error)" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ $package[ 'ctrls' ][] = 'delete_note_form';
|
||||||
$package[ 'ctrls' ][] = 'delete_note';
|
$package[ 'ctrls' ][] = 'delete_note';
|
||||||
$package[ 'ctrls' ][] = 'delete_task_form';
|
$package[ 'ctrls' ][] = 'delete_task_form';
|
||||||
$package[ 'ctrls' ][] = 'delete_task';
|
$package[ 'ctrls' ][] = 'delete_task';
|
||||||
|
$package[ 'ctrls' ][] = 'dependency_add';
|
||||||
|
$package[ 'ctrls' ][] = 'dependency_add_form';
|
||||||
$package[ 'ctrls' ][] = 'edit_note_form';
|
$package[ 'ctrls' ][] = 'edit_note_form';
|
||||||
$package[ 'ctrls' ][] = 'edit_note';
|
$package[ 'ctrls' ][] = 'edit_note';
|
||||||
$package[ 'ctrls' ][] = 'edit_task_form';
|
$package[ 'ctrls' ][] = 'edit_task_form';
|
||||||
|
|
|
@ -353,3 +353,97 @@ class Ctrl_EditNoteForm
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Ctrl_DependencyAddForm
|
||||||
|
extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function handle( Page $page )
|
||||||
|
{
|
||||||
|
// Check selected note
|
||||||
|
try {
|
||||||
|
$id = (int) $this->getParameter( 'to' );
|
||||||
|
} catch ( ParameterException $e ) {
|
||||||
|
return 'tasks';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tasks = Loader::DAO( 'tasks' );
|
||||||
|
$task = $tasks->get( $id );
|
||||||
|
if ( $task === null ) {
|
||||||
|
return 'tasks';
|
||||||
|
}
|
||||||
|
if ( $task->completed_at !== null || empty( $task->possibleDependencies ) ) {
|
||||||
|
return 'tasks/view?id=' . $id;
|
||||||
|
}
|
||||||
|
$page->setTitle( $task->title . ' (task)' );
|
||||||
|
|
||||||
|
// Generate form
|
||||||
|
$form = Loader::Create( 'Form' , 'Add dependency' , 'add-dep' )
|
||||||
|
->addField( Loader::Create( 'Field' , 'to' , 'hidden' )
|
||||||
|
->setDefaultValue( $id ) );
|
||||||
|
$this->addDependencySelector( $form , $task->possibleDependencies );
|
||||||
|
return $form->setURL( 'tasks/view?id=' . $id )
|
||||||
|
->addController( Loader::Ctrl( 'dependency_add' ) )
|
||||||
|
->controller( );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addDependencySelector( $form , $possibleDependencies )
|
||||||
|
{
|
||||||
|
$form->addField( $select = Loader::Create( 'Field' , 'dependency' , 'select' )
|
||||||
|
->setDescription( 'Dependency to add:' )
|
||||||
|
->addOption( '' , '(please select a task)' ) );
|
||||||
|
|
||||||
|
$depsByItem = $this->getDependenciesByItem( $possibleDependencies );
|
||||||
|
$items = $this->getItemsToDisplay( $depsByItem );
|
||||||
|
foreach ( $items as $item ) {
|
||||||
|
$prefix = '-' . str_repeat( '--' , $item->depth );
|
||||||
|
$name = $prefix . ' ' . $item->name;
|
||||||
|
$select->addOption( 'I' . $item->id , $name , true );
|
||||||
|
if ( ! array_key_exists( $item->id , $depsByItem ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $depsByItem[ $item->id ] as $task ) {
|
||||||
|
$select->addOption( $task->id , $prefix . '-> ' . $task->title );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDependenciesByItem( $possibleDependencies )
|
||||||
|
{
|
||||||
|
$dbi = array( );
|
||||||
|
foreach ( $possibleDependencies as $pDep ) {
|
||||||
|
$dbi[ $pDep->item ][] = $pDep;
|
||||||
|
}
|
||||||
|
return $dbi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getItemsToDisplay( $depsByItem )
|
||||||
|
{
|
||||||
|
$dao = Loader::DAO( 'items' );
|
||||||
|
$allItems = $dao->getTreeList( );
|
||||||
|
$found = array( );
|
||||||
|
foreach ( array_keys( $depsByItem ) as $id ) {
|
||||||
|
if ( array_key_exists( $id , $found ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$item = $dao->get( $id );
|
||||||
|
foreach ( $dao->getLineage( $item ) as $parent ) {
|
||||||
|
$found[ $parent ] = 1;
|
||||||
|
}
|
||||||
|
$found[ $id ] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array( );
|
||||||
|
foreach ( $allItems as $item ) {
|
||||||
|
if ( array_key_exists( $item->id , $found ) ) {
|
||||||
|
array_push( $result , $item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ class Page_TasksTasks
|
||||||
'view' => 'view_task' ,
|
'view' => 'view_task' ,
|
||||||
'notes/edit' => 'edit_note_form' ,
|
'notes/edit' => 'edit_note_form' ,
|
||||||
'notes/delete' => 'delete_note_form' ,
|
'notes/delete' => 'delete_note_form' ,
|
||||||
|
'deps/add' => 'dependency_add_form' ,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue