tasks/includes/t-tasks/views.inc.php

439 lines
12 KiB
PHP
Raw Normal View History

<?php
class View_TasksList
extends BaseURLAwareView
{
protected $tasks;
protected $dao;
public function __construct( $tasks , $features = array( 'item' , 'assigned' , 'deps' , 'completed' ) )
{
$this->tasks = $tasks;
$this->features = array_combine( $features , array_fill( 0 , count( $features ) , 1 ) );
$this->dao = Loader::DAO( 'tasks' );
}
public final function render( )
{
if ( empty( $this->tasks ) ) {
return HTML::make( 'div' )
->setAttribute( 'class' , 'no-table' )
->appendText( 'No tasks to display.' );
}
return HTML::make( 'dl' )
->append( $this->generateList( ) )
->setAttribute( 'class' , 'tasks' );
}
private function generateList( )
{
$result = array( );
$prevPriority = 6;
foreach ( $this->tasks as $task ) {
$priority = ( $task->completed_by === null ) ? $task->priority : -1;
if ( $priority !== $prevPriority ) {
if ( $priority == -1 ) {
$text = 'Completed tasks';
$extraClass = ' completed';
} else {
$text = $this->dao->translatePriority( $priority ) . ' priority';
$extraClass = '';
}
$prevPriority = $priority;
array_push( $result , HTML::make( 'dt' )
->setAttribute( 'class' , 'sub-title' . $extraClass )
->appendText( $text ) );
}
$result = array_merge( $result , $this->generateItem( $task ) );
}
return $result;
}
protected function generateItem( $task )
{
$cell = array( );
array_push( $cell , HTML::make( 'dt' )
->appendElement( HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/tasks/view?id=' . $task->id )
->appendText( $task->title ) ) );
$this->addParent( $cell , $task );
$classes = array( );
$addedAt = strtotime( $task->added_at );
$addedAtDate = date( 'd/m/o' , $addedAt );
$addedAtTime = date( 'H:i:s' , $addedAt );
array_push( $cell ,
HTML::make( 'dd' )->appendText( "Added $addedAtDate at $addedAtTime by {$task->added_by}" ) );
if ( $task->completed_by !== null ) {
$this->generateCompletedTask( $cell , $classes , $task );
} else {
if ( $task->unsatisfied_direct_dependencies > 0 ) {
$this->generateMissingDependencies( $cell , $classes , $task );
}
if ( $task->incomplete_subtasks > 0 ) {
$this->generateMissingSubtasks( $cell , $classes , $task );
}
if ( $task->unsatisfied_inherited_dependencies > 0 ) {
$this->generateMissingInherited( $cell , $classes , $task );
}
if ( $task->assigned_to !== null ) {
$this->generateAssignedTask( $cell , $classes , $task );
}
}
if ( ! empty( $classes ) ) {
foreach ( $cell as $entry ) {
$entry->setAttribute( 'class' , join( ' ' , array_unique( $classes ) ) );
}
}
return $cell;
}
protected function addParent( &$cell , $task )
{
if ( ! array_key_exists( 'item' , $this->features ) ) {
return;
}
$this->addItem( $cell , $task );
if ( $task->parent_task !== null ) {
$this->addParentTask( $cell , $task );
}
}
protected function addItem( &$cell , $task )
{
$itemsDao = Loader::DAO( 'items' );
$item = $itemsDao->get( $task->item );
$lineage = $itemsDao->getLineage( $item );
array_push( $lineage , $item->id );
$contents = array( );
foreach ( Loader::DAO( 'items' )->getAll( $lineage ) as $ancestor ) {
if ( ! empty( $contents ) ) {
array_push( $contents , ' &raquo; ' );
}
array_push( $contents , HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/items/view?id=' . $ancestor->id )
->appendText( $ancestor->name ) );
}
array_unshift( $contents, 'On ' );
array_push( $cell , HTML::make( 'dd' )->append( $contents ) );
}
protected function addParentTask( &$cell , $task )
{
$parents = $this->dao->getLineage( $task );
$contents = array( );
foreach ( $parents as $parent ) {
list( $id , $title ) = $parent;
if ( ! empty( $contents ) ) {
array_push( $contents , ' &raquo; ' );
}
array_push( $contents , HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/tasks/view?id=' . $id )
->appendText( $title ) );
}
array_push( $cell , HTML::make( 'dd' )
->appendText( 'Sub-task of ' )
->append( $contents ) );
}
protected function generateMissingDependencies( &$cell , &$classes , $task )
{
if ( ! array_key_exists( 'deps' , $this->features ) ) {
return;
}
if ( $task->unsatisfied_direct_dependencies > 1 ) {
$end = 'ies';
} else {
$end = 'y';
}
array_push( $cell ,
$md = HTML::make( 'dd' )->appendText( "{$task->unsatisfied_direct_dependencies} missing dependenc$end" ) );
if ( $task->unsatisfied_direct_dependencies != $task->unsatisfied_transitive_dependencies ) {
$md->appendText( " ({$task->unsatisfied_transitive_dependencies} when counting transitive dependencies)" );
}
array_push( $classes , 'missing-deps' );
}
protected function generateMissingSubtasks( &$cell , &$classes , $task )
{
if ( ! array_key_exists( 'deps' , $this->features ) ) {
return;
}
if ( $task->incomplete_subtasks > 1 ) {
$end = 's';
} else {
$end = '';
}
array_push( $cell , HTML::make( 'dd' )->appendText(
"{$task->incomplete_subtasks} incomplete sub-task$end (out of {$task->total_subtasks})" ) );
array_push( $classes , 'missing-deps' );
}
protected function generateMissingInherited( &$cell , &$classes , $task )
{
if ( ! array_key_exists( 'deps' , $this->features ) ) {
return;
}
if ( $task->unsatisfied_inherited_dependencies > 1 ) {
$end = 'ies';
} else {
$end = 'y';
}
array_push( $cell , HTML::make( 'dd' )->appendText(
"{$task->unsatisfied_inherited_dependencies} unsatisfied dependenc$end in parent task(s)" ) );
array_push( $classes , 'missing-deps' );
}
protected function generateAssignedTask( &$cell , &$classes , $task )
{
if ( ! array_key_exists( 'assigned' , $this->features ) ) {
return;
}
array_push( $cell , HTML::make( 'dd' )->appendText( 'Assigned to ' . $task->assigned_to ) );
array_push( $classes , 'assigned' );
}
protected function generateCompletedTask( &$cell , &$classes , $task )
{
if ( ! array_key_exists( 'completed' , $this->features ) ) {
return;
}
$completedAt = strtotime( $task->completed_at );
$completedAtDate = date( 'd/m/o' , $completedAt );
$completedAtTime = date( 'H:i:s' , $completedAt );
array_push( $cell , HTML::make( 'dd' )->appendText(
"Completed $completedAtDate at $completedAtTime by {$task->completed_by}" ) );
array_push( $classes , 'completed' );
}
}
class View_TaskDetails
extends BaseURLAwareView
{
private $task;
public function __construct( $task )
{
$this->task = $task;
}
public function render( )
{
$list = HTML::make( 'dl' )
->setAttribute( 'class' , 'tasks' )
->appendElement( HTML::make( 'dt' )
->appendText( 'On item:' ) )
->appendElement( HTML::make( 'dd' )
->append( $this->formatPlaceLineage( $this->task->item ) ) );
if ( $this->task->parent_task !== null ) {
$parents = Loader::DAO( 'tasks' )->getLineage( $this->task );
$contents = array( );
foreach ( $parents as $parent ) {
list( $id , $title ) = $parent;
if ( ! empty( $contents ) ) {
array_push( $contents , ' &raquo; ' );
}
array_push( $contents , HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/tasks/view?id=' . $id )
->appendText( $title ) );
}
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Sub-task of:' ) )
->appendElement( HTML::make( 'dd' )
->append( $contents ) );
}
if ( $this->task->description != '' ) {
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Description:' ) )
->appendElement( HTML::make( 'dd' )
->appendRaw( $this->formatDescription( ) ) );
}
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Added:' ) )
->appendElement( HTML::make( 'dd' )
->appendText( $this->formatAction( $this->task->added_at , $this->task->added_by ) ) );
if ( $this->task->completed_by === null ) {
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Priority:' ) )
->appendElement( HTML::make( 'dd' )
->appendText( Loader::DAO( 'tasks' )
->translatePriority( $this->task->priority ) ) );
if ( $this->task->assigned_to === null ) {
$list->appendElement( HTML::make( 'dt' )
->setAttribute( 'class' , 'unassigned-task' )
->appendText( 'Unassigned!' ) );
} else {
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Assigned to:' ) )
->appendElement( HTML::make( 'dd' )
->appendText( $this->task->assigned_to ) );
}
} else {
$list->appendElement( HTML::make( 'dt' )
->appendText( 'Completed:' ) )
->appendElement( HTML::make( 'dd' )
->appendText( $this->formatAction(
$this->task->completed_at , $this->task->completed_by ) ) );
}
return $list;
}
private function formatPlaceLineage( $item )
{
$lineage = $item->lineage;
array_push( $lineage , $item->id );
$contents = array( );
foreach ( Loader::DAO( 'items' )->getAll( $lineage ) as $ancestor ) {
if ( ! empty( $contents ) ) {
array_push( $contents , ' &raquo; ' );
}
array_push( $contents , HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/items/view?id=' . $ancestor->id )
->appendText( $ancestor->name ) );
}
return $contents;
}
private function formatDescription( )
{
$description = HTML::from( $this->task->description );
return preg_replace( '/\n/s' , '<br/>' , $description );
}
private function formatAction( $timestamp , $user )
{
$ts = strtotime( $timestamp );
$tsDate = date( 'd/m/o' , $ts );
$tsTime = date( 'H:i:s' , $ts );
return "$tsDate at $tsTime by $user";
}
}
class View_TaskNote
implements View
{
private $note;
public function __construct( $note )
{
$this->note = $note;
}
public function render( )
{
$text = HTML::make( 'p' )
->appendRaw( preg_replace( '/\n/s' , '<br/>' , HTML::from( $this->note->text ) ) );
$ts = strtotime( $this->note->added_at );
$tsDate = date( 'd/m/o' , $ts );
$tsTime = date( 'H:i:s' , $ts );
$details = HTML::make( 'div')
->setAttribute( 'style' , 'font-size: 9pt' )
->appendElement( HTML::make( 'em' )
->appendText( "Note added $tsDate at $tsTime by {$this->note->author}" ) );
return array( $text , $details );
}
}
class View_TaskDependencies
extends BaseURLAwareView
{
private $task;
private $reverse;
public function __construct( $task , $reverse )
{
$this->task = $task;
$this->reverse = $reverse;
}
public function render( )
{
$source = $this->reverse ? 'reverseDependencies' : 'dependencies';
if ( empty( $this->task->$source ) ) {
return HTML::make( 'div' )
->setAttribute( 'class' , 'no-table' )
->appendText( 'This task has no dependencies.' );
}
$list = HTML::make( 'ul' )->setAttribute( 'class' , 'dep-list' );
$prevItem = null;
$itemList = null;
foreach ( $this->task->$source as $dependency ) {
if ( $prevItem !== $dependency->item ) {
$itemList = HTML::make( 'ul' );
$list->appendElement( HTML::make( 'li' )
->appendText( 'In ' )
->appendElement( HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/items/view?id=' . $dependency->item )
->appendText( $dependency->item_name ) )
->appendElement( $itemList ) );
$prevItem = $dependency->item;
} elseif ( $itemList === null ) {
$itemList = $list;
}
$entry = HTML::make( 'li' )->appendElement(
$link = HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/tasks/view?id=' . $dependency->id )
->appendText( $dependency->title ) );
if ( ! $this->reverse ) {
$link->setAttribute( 'class' , ( $dependency->completed == 't' )
? 'satisfied' : 'missing' );
if ( $this->task->completed_at === null ) {
$entry->appendText( ' (' )
->appendElement( HTML::make( 'a' )
->setAttribute( 'href' , $this->base . '/tasks/deps/delete?from='
. $this->task->id . '&to=' . $dependency->id )
->appendText( 'remove') )
->appendText( ')' );
if ( $dependency->missing_dependencies != 0 ) {
$end = $dependency->missing_dependencies > 1 ? 'ies' : 'y';
$entry->appendElement( HTML::make( 'ul' )
->appendElement( $mdeps = HTML::make( 'li' ) ) );
$mdeps->appendText( $dependency->missing_dependencies
. " missing dependenc$end (transitively)" );
}
}
}
$itemList->appendElement( $entry );
}
return $list;
}
}