Creating a CodeIgniter App (Part 6): Tasks

We finally got to the end of the series Creating a CodeIgniter App. We will conclude our Simple Task Board app with the development of the tasks section. This includes the creation of tasks for each project, the exhibition of these tasks in the dashboard and, of course, the exhibition of these tasks in a agile like task board.

To accomplish out task we’ll create a table in the database, a controller (we’ll also update two other controllers), a model and a view (we’ll also update two other views, the menu and the Template library). In order to complete it, some CSS and JavaScript.

Introduction

I’m assuming that at this point you already understood how CodeIgniter works, so I’ll try to be quick. Like the last article, I’ll paste each block of code and explain right after only the most important parts. So let’s get started.

Database

Let’s create a table to store the tasks’ information. Run the following script in you database:

CREATE TABLE IF NOT EXISTS `task` (
  `project` int(10) unsigned NOT NULL,
  `id` int(10) unsigned NOT NULL,
  `user` int(10) unsigned NOT NULL,
  `status` tinyint(4) unsigned NOT NULL,
  `title` varchar(50) NOT NULL,
  `priority` tinyint(4) unsigned NOT NULL,
  `description` text NOT NULL,
  `files` text NOT NULL,
  `database` text NOT NULL,
  `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`project`,`id`),
  KEY `position` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Tasks Controller

First we’ll create the controller which will handle the tasks’ logic. Crate the file task.php inside application/controllers.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Task extends CI_Controller {
    
    function Task()
    {
        parent::__construct();
        
        if(!$this->session->userdata('logged'))
            redirect('login');
    }
    
    public function index()
    {
        redirect('dashboard');
    }

    public function add($project)
    {
        $this->load->model('task_model');
        
        $data['page_title']  = "New Task";
        $data['title']       = '';
        $data['description'] = '';
        $data['priority']    = '2';
        $data['files']       = '';
        $data['database']    = '';
        
        $data['project']  = $project;
        $data['users'] = $this->task_model->get_related_users($project);
        $data['user'] = $this->session->userdata('user');
        
        $this->template->show('task_add', $data);
    }

    public function edit($project, $id)
    {
        $this->load->model('task_model');
        
        $data = $this->task_model->get($project, $id);
        $data['page_title']  = "Edit Task #".$id;
        
        $data['project']  = $project;
        $data['users'] = $this->task_model->get_related_users($project);
        
        $this->template->show('task_add', $data);
    }
    
    public function save()
    {
        $this->load->model('task_model');
        
        $sql_data = array(
            'project' => $this->input->post('project'),
            'status' => ($this->input->post('status'))?$this->input->post('status'):0,
            'title' => $this->input->post('title'),
            'description' => $this->input->post('description'),
            'priority' => $this->input->post('priority'),
            'user'     => $this->input->post('user'),
            'files'    => ($this->input->post('files'))?$this->input->post('files'):'',
            'database' => ($this->input->post('database'))?$this->input->post('database'):''
        );
        
        if ($this->input->post('id'))
            $this->task_model->update($this->input->post('project'), $this->input->post('id'),$sql_data);
        else
            $this->task_model->create($sql_data);

        redirect('project/tasks/'.$this->input->post('project'));
    }
    
    public function move($project, $id, $status)
    {
        $this->load->model('task_model');
        
        $sql_data = array(
            'status' => $status
        );

        $this->task_model->update($project, $id, $sql_data);

        redirect('project/tasks/'.$project);
    }
    
    public function remove($project, $id)
    {
        $this->load->model('task_model');
        $this->task_model->delete($project, $id);

        redirect('project/tasks/'.$project);
    }
}

Nothing new here. The methods are quite similar to those of the project.php controller, with exception of the methods move() and remove(). The method move() is executed when we move a task from one phase to another (for example, when it is in the “To Do” list and it is started, going into “In Progress”). The second method, remove() does exactly what the name says, removes a task from the database.

Model

Now let’s continue with the model, which will define some methods to be used in different places. Include this code in a new file (create it inside application/models) called task_model.php.

<?php

class Task_model extends CI_Model {

    public function create($data)
    {
        $this->db->select_max('id');
        $this->db->where('project', $data['project']);
        $get = $this->db->get('task');
        
        if($get->num_rows > 0) {
            $row = $get->row_array();
            $data['id'] = $row['id'] + 1;
        } else
            $data['id'] = 1;
        
        $insert = $this->db->insert('task', $data);
        return $insert;
    }


    public function update($project, $id, $data)
    {
        $this->db->where('project', $project);
        $this->db->where('id', $id);
        $update = $this->db->update('task', $data);
        return $update;
    }

    public function get($project, $id = false, $status = false)
    {
        $this->db->where('project', $project);
        if ($id) $this->db->where('id', $id);
        if ($status) $this->db->where('status', $status);
        $this->db->order_by('status', 'asc');
        $this->db->order_by('priority', 'asc');
        $get = $this->db->get('task');

        if ($id) return $get->row_array();
        if($get->num_rows > 0) return $get->result_array();
        return array();
    }
    
    public function get_user_tasks($user)
    {
        $this->db->select('t.*');
        $this->db->distinct();
        $this->db->from('task t');
        $this->db->where('t.user', $user);
        $this->db->where('t.status !=', 3);
        $this->db->order_by('t.status', 'desc');
        $get = $this->db->get();

        if($get->num_rows > 0) return $get->result_array();
        return array();
    }
    
    public function get_project_user_tasks($project, $user)
    {
        $this->db->select('t.*');
        $this->db->distinct();
        $this->db->from('task t');
        $this->db->where('t.user', $user);
        $this->db->where('t.project', $project);
        $this->db->where('t.status !=', 3);
        $this->db->order_by('t.status', 'desc');
        $get = $this->db->get();

        if($get->num_rows > 0) return $get->result_array();
        return array();
    }
    
    public function get_related_users($project)
    {
        $this->db->select('u.*, up.project');
        
        $this->db->from('user u');
        $this->db->join('user_project up', 'up.user = u.id and up.project = '.$project, 'left');
        $this->db->order_by('u.email', 'asc');
        $get = $this->db->get();

        if($get->num_rows > 0) return $get->result_array();
        return array();
    }

    public function delete($project, $id)
    {
        $this->db->where('project', $project);
        $this->db->where('id', $id);
        $this->db->delete('task');
    }

}

Once again, the methods are very similar to those of the project model. Here follows the explanation of the different ones:

  • update($project, $id, $data): the method that updates the task receives the project and the task IDs to identify the task being updated.
  • get($project, $id = false, $status = false): the method get retrieves the tasks’ data according to the project. If the $id was informed, the method gets the data for this task. If the $status was informed, the method returns the tasks according to the status (which identifies the phase) – this will be used to assemble the task board.
  • get_user_tasks($user): gets the user’s tasks.
  • get_project_user_tasks($project, $user): gets the user’s tasks inside a project.
  • get_related_users($project): gets the users related to a project.

Other Controllers

Now that we finished the tasks’ model, we can update the dashboard.php and project.php controllers. We’ll use some of the functions created in the previous model.

dashboard.php

We have a few things to add in different parts of this controller. Here goes all the code, the explanation follows:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Dashboard extends CI_Controller {
    
    private $STATUS;
    
    function Dashboard()
    {
        parent::__construct();
        
        $this->STATUS = array(
            0 => 'To Do',
            1 => 'In Progress',
            2 => 'Testing',
            3 => 'Done'
        );
        
        if(!$this->session->userdata('logged'))
            redirect('login');        
    }
    
    public function index()
    {
        //Load models
        $this->load->model('project_model');
        $this->load->model('task_model');
        
        //Load projects
        $projects = $this->project_model->get_user_related($this->session->userdata('user'));
        
        foreach ($projects as $key => $project) {
            $projects[$key]['tasks'] = $this->task_model->get_project_user_tasks($project['id'], $this->session->userdata('user'));
        }
        
        $data['projects'] = $projects;
        
        // Load tasks
        $data['tasks'] = $this->task_model->get_user_tasks($this->session->userdata('user'));
        
        $data['page_title']  = "Dashboard";
        $data['status'] = $this->STATUS;
        
        // Load View
        $this->template->show('dashboard', $data);
    }

}

We added the status property which will contain the text for each status value. This property will be sent to the view inside the index() method. Besides that, we also loaded the task_model (just created) and we updated the projects foreach to assign the tasks of each project into the $projects array.

project.php

In the projects’ controller, that we created in the last part of the series, we need to include the tasks in the tasks() method (there was a TODO for this). Just replace the TODO for this:

        // Load tasks
        $this->load->model('task_model');
        $tasks = $this->task_model->get($project_id);
        
        foreach ($tasks as $task) {
            if ($task['status'] == 0) {
                $data['stories'][] = $task;
            } elseif ($task['status'] == 1) {
                $data['tasks'][] = $task;
            } elseif ($task['status'] == 2) {
                $data['tests'][] = $task;
            } elseif ($task['status'] == 3) {
                $data['done'][] = $task;
            }
        }

This code will get all project’s tasks and will loop through these items, assigning them to another array, according to the item’s status. This will create 4 different arrays, each one containing tasks belonging to an specific phase (or with an specific status). In the view we will access only these arrays: $stories, $tasks, $tests and $done.

Views

Everything is done with relation to the system’s logic. Now we will work with the views. First let’s update the menu, in order to access the new functionalities.

Menu

Open the application/views/template/menu.php file. We’ll change only two small parts, but I’m copying the entire code just in case:

<div class="home-title blue-gradient">Simple Task Board</div>
<div id="menu">
    <?php if($view == 'dashboard') { ?>
        <!-- Dashboard menu -->
        <?php echo anchor('user', 'Edit Users', 'class="btn btn_users"'); ?>
		<?php echo anchor('project/add', 'Add new project', 'class="btn btn_add"'); ?>
    <?php } elseif($view == 'task_board') { ?>
        <!-- Task board menu -->
        <?php echo anchor('dashboard', 'Dashboard', 'class="btn btn_dashboard"'); ?>
        <?php echo anchor('project/edit/'.$project, 'Edit project', 'class="btn btn_edit"'); ?>
		<?php echo anchor('task/add/'.$project, 'Add new task', 'class="btn btn_add"'); ?>
    <?php } elseif($view == 'return_to_tasks') { ?>
        <!-- Projects menu -->
        <?php echo anchor('dashboard', 'Dashboard', 'class="btn btn_dashboard"'); ?>
        <?php echo anchor('project/tasks/'.$project, 'Task Board', 'class="btn btn_taskboard"'); ?>
    <?php } elseif($view == 'projects') { ?>
        <!-- Projects menu -->
        <?php echo anchor('dashboard', 'Dashboard', 'class="btn btn_dashboard"'); ?>
    <?php } elseif($view == 'users') { ?>
        <!-- Users menu -->
        <?php echo anchor('dashboard', 'Dashboard', 'class="btn btn_dashboard"'); ?>
        <?php echo anchor('user/add', 'Add new user', 'class="btn btn_add"'); ?>
    <?php } ?>
    <?php echo anchor('login/logout', 'Logout', 'class="btn btn_logout"'); ?>
    <div class="clear"></div>
</div>
<div id="page-title">
    <?php echo $page_title; ?>
	<?php if($view == 'task_board') { ?>
    <span class="switch-project-view-event global-tasks btn" title="Show all"></span>
    <?php } ?>
</div>

Updates:

  • Task board menu: we included a link for “task/add/$project”, where we can include a new task.
  • Page title: right after showing the $page_title, we included a SPAN, if the menu is the task_board. This SPAN will be a button that, through JavaScript, will show/hide the tasks belonging to other users. That’s why this button will only be displayed when we are in the task board.

In order to make it 100%, we’ll add the necessary CSS:

CSS

After the definition of #associated-users add the following:

.global-tasks, .user-tasks{
    background-repeat: no-repeat;
    background-position: 50% 50%;
    margin:2px 8px;
    padding:2px;
    width:16px;
    height:16px;
    cursor:pointer;
    float:right;
}
.global-tasks{
    background-color:#FFB51B;background-image:url(../images/global.png);
    background-image:url(../images/global.png), -webkit-gradient(linear, left top, left bottom, from(#FFD500), to(#FF9C30));
    background-image:url(../images/global.png), -webkit-linear-gradient(top,#FFD500,#FF9C30); /* Chrome 10+, Saf5.1+ */
    background-image:url(../images/global.png), -moz-linear-gradient(top,#FFD500,#FF9C30); /* FF3.6+ */
    background-image:url(../images/global.png), -ms-linear-gradient(top,#FFD500,#FF9C30); /* IE10 */
    background-image:url(../images/global.png), -o-linear-gradient(top,#FFD500,#FF9C30); /* Opera 11.10+ */
    background-image:url(../images/global.png), linear-gradient(top,#FFD500,#FF9C30)
}
.global-tasks:hover{background-color:#FB8F19;background-image:url(../images/global.png);
    background-image:url(../images/global.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F78400), to(#FF9C30));
    background-image:url(../images/global.png), -webkit-linear-gradient(top,#F78400,#FF9C30); /* Chrome 10+, Saf5.1+ */
    background-image:url(../images/global.png), -moz-linear-gradient(top,#F78400,#FF9C30); /* FF3.6+ */
    background-image:url(../images/global.png), -ms-linear-gradient(top,#F78400,#FF9C30); /* IE10 */
    background-image:url(../images/global.png), -o-linear-gradient(top,#F78400,#FF9C30); /* Opera 11.10+ */
    background-image:url(../images/global.png), linear-gradient(top,#F78400,#FF9C30)
}
.user-tasks{
    background-color:#FFB51B;background-image:url(../images/user.png);
    background-image:url(../images/user.png), -webkit-gradient(linear, left top, left bottom, from(#FFD500), to(#FF9C30));
    background-image:url(../images/user.png), -webkit-linear-gradient(top,#FFD500,#FF9C30); /* Chrome 10+, Saf5.1+ */
    background-image:url(../images/user.png), -moz-linear-gradient(top,#FFD500,#FF9C30); /* FF3.6+ */
    background-image:url(../images/user.png), -ms-linear-gradient(top,#FFD500,#FF9C30); /* IE10 */
    background-image:url(../images/user.png), -o-linear-gradient(top,#FFD500,#FF9C30); /* Opera 11.10+ */
    background-image:url(../images/user.png), linear-gradient(top,#FFD500,#FF9C30)
}
.user-tasks:hover{background-color:#FB8F19;background-image:url(../images/user.png);
    background-image:url(../images/user.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F78400), to(#FF9C30));
    background-image:url(../images/user.png), -webkit-linear-gradient(top,#F78400,#FF9C30); /* Chrome 10+, Saf5.1+ */
    background-image:url(../images/user.png), -moz-linear-gradient(top,#F78400,#FF9C30); /* FF3.6+ */
    background-image:url(../images/user.png), -ms-linear-gradient(top,#F78400,#FF9C30); /* IE10 */
    background-image:url(../images/user.png), -o-linear-gradient(top,#F78400,#FF9C30); /* Opera 11.10+ */
    background-image:url(../images/user.png), linear-gradient(top,#F78400,#FF9C30)
}
.project-task{
    display:none;
}

In this CSS we defined how the SPAN will look. We need an image to finish this button:

In the last style definition we will hide all tasks that belong to the project but doesn’t belong to the user. If the user wants he will be able to click this SPAN element and this style will be updated, making those tasks visible. We need some jQuery to do that.

JavaScript

    /* Dashboard actions*/
    $('.switch-project-view-event').click(function(){
        if($(this).hasClass('global-tasks')) {
            $('.project-task').show('slow');
            $(this).attr('title', 'Show mine');
            $(this).removeClass('global-tasks').addClass('user-tasks');
        } else {
            $('.project-task').hide('slow');
            $(this).attr('title', 'Show all');
            $(this).removeClass('user-tasks').addClass('global-tasks');
        }
    });

Add this code in the file scripts.js, inside the $(document).ready block, in order to get the code executed when the document finished loading. According to the button class we will show or hide the project tasks that are not related to the user. We’ll also modify the title and the class of the button, in order to update it’s appearance.

Now that we finished the menu, let1s create the view task_add.php, which will enable the creation of tasks.

task_add.php

Create this file inside the application/views folder.

<?php
// Load Menu
$this->template->menu('return_to_tasks');
?>

<div id="container">

    <?php echo form_open('task/save'); ?>

    <table>
        <tr>
            <td>
                <?php echo form_label('Title', 'title'); ?>
            </td>
            <td>
                <?php echo form_input('title', $title, 'maxlength="50"'); ?>
            </td>
        </tr>
        <tr>
            <td>
                <?php echo form_label('Priority', 'priority'); ?>
            </td>
            <td>
                <?php $options = array('0' => 'Very High', '1' => 'High', '2' => 'Normal', '3' => 'Low', '4' => 'Very Low');
                      echo form_dropdown('priority', $options, $priority); ?>
            </td>
        </tr>
        <tr>
            <td>
                <?php echo form_label('Description', 'text'); ?>
            </td>
            <td>
                <?php
                $data = array('name'        => 'description',
                              'id'          => 'description',
                              'value'       => $description,
                              'rows'        => '6',
                              'cols'        => '80');

                echo form_textarea($data); ?>
            </td>
        </tr>
        <tr>
            <td>
                <?php echo form_label('Assigned to', 'user'); ?>
            </td>
            <td>
                <?php
                $options = array();
                foreach ($users as $value) {
                    $options[$value['id']] = $value['email'];
                }
                echo form_dropdown('user', $options, $user);
                ?>
            </td>
        </tr>
        <?php if (isset($id)) { ?>
        <tr>
            <td>
                <?php echo form_label('Files changed', 'files'); ?>
            </td>
            <td>
                <?php
                $data = array('name'        => 'files',
                              'id'          => 'files',
                              'value'       => $files,
                              'rows'        => '3',
                              'cols'        => '80');

                echo form_textarea($data); ?>
            </td>
        </tr>
        <tr>
            <td>
                <?php echo form_label('Database changes', 'database'); ?>
            </td>
            <td>
                <?php
                $data = array('name'        => 'database',
                              'id'          => 'database',
                              'value'       => $database,
                              'rows'        => '3',
                              'cols'        => '80');

                echo form_textarea($data); ?>
            </td>
        </tr>
        <?php } ?>
        <tr>
                <td colspan="2">
                    <?php if (isset($id)) echo form_hidden('id', $id); ?>
                    <?php if (isset($status)) echo form_hidden('status', $status); ?>
                    <?php if (isset($project)) echo form_hidden('project', $project); ?>

                    <div class="form-save-buttons">
                        <?php echo form_submit('save', 'Save', 'class="btn-blue"'); ?>
                        <?php echo form_button('cancel', 'Cancel', 'class="btn-blue" onClick="history.go(-1)"');; ?>
                        <?php
                        if(isset($id)) {
                            $remove_url = base_url().'task/remove/'.$project.'/'.$id;
                            echo form_button('remove', 'Remove', 'class="btn-blue" id="remove-task" target-url="'.$remove_url.'"');
                        } ?>
                    </div>
                </td>
        </tr>
    </table>

    <?php echo form_close(); ?>

</div>

This view is just a form to insert or edit a task. In this case we have a small difference which is the button to remove the task, in the end of the file. This button has a JavaScript associated which will display the deletion popup, like when we remove an user (done in part 4).

JavaScript

Add this code inside scripts.js and $(document).ready like we did before.

    /* Task actios */
    $('#remove-task').click(function(){
        var targetUrl = $(this).attr('target-url');
        
        $('#dialog-confirm').dialog({
            resizable: false,
            height:140,
            modal: true,
            buttons: {
                "Remove": function() {
                    window.location = targetUrl;
                },
                Cancel: function() {
                    $( this ).dialog( "close" );
                }
            }
        });
        
        return false;
    });

This code is similar to the one for the users. Our next step is to display the tasks in the Dashboard (views/dashboard.php) and in the Task Board (views/task_board.php).

dashboard.php

In this view we will display the tasks’ data that was loaded in the controller. Inside the file we have a DIV with the ID “container”. After the opening tag of this DIV, paste the following code:

    <?php if(isset($tasks)) { ?>
    <div id="dash_tasks" class="dash_wrap">
        <div id="dash_task_title" class="dash_wrap_title blue-gradient">
            Tasks
        </div>
        <div id="dash_task_items" class="dash_wrap_items">
            <ul>
            <?php if($tasks) { ?>
                <?php $listControl = 0; ?>
                <?php foreach ($tasks as $task) { ?>
                    <li>
                    <?php echo anchor('task/edit/'.$task['project'].'/'.$task['id'], '#'.$task['id'].' - '.$task['title']); ?>
                    (<?php echo $status[$task['status']] ?>)
                    </li>
                    <?php $listControl++; ?>
                    <?php if($listControl % 10 == 0) { ?>
                </ul><ul>
                    <?php } ?>
                <?php } ?>
            <?php } else { ?>
                There are no tasks assigned to you.
            <?php } ?>
            </ul>
        </div>
        <div class="clear"></div>
    </div>
    <?php } ?>

This code will display all user’s tasks, from all projects.

task_board.php

When you open this file, you’ll see we have an empty container DIV. Paste the following inside it:

    <?php if(isset($transports)) { ?>
        <div class="transport">
        <?php foreach ($transports as $transport) { ?>
            <p id="transport_<?php echo $transport['id']; ?>" class="transport_info"><?php
            echo anchor('transport/edit/'.$transport['id'], 'Transport #'.$transport['id']).' - ';
            $task_list = explode(",", $transport['tasks']);
            $files = explode(",", $transport['files']);
            $database = explode(",", $transport['database']);
            echo "Contents: ".
                (($transport['tasks'])?count($task_list):0)." tasks, ".
                (($transport['files'])?count($files):0)." files changed, ".
                (($transport['database'])?count($database):0)." tables or fields updated. ".
                anchor('transport/close/'.$transport['id'], 'Close'); ?></p>
        <?php } ?>
        </div>
    <?php } ?>

    <?php if(isset($stories) || isset($tasks) || isset($tests) || isset($done)) { ?>
    <table class="board">
        <tr>
            <th class="blue-gradient">To Do</th>
            <th class="blue-gradient">In Progress</th>
            <th class="blue-gradient">Testing</th>
            <th class="blue-gradient">Done</th>
        </tr>
        <tr>
            <td>
                <?php
                if(isset($stories)) {
                    // Load Tasks
                    $this->template->tasks($project, $stories);
                } ?>
            </td>
            <td>
                <?php if(isset($tasks)) {
                    // Load Tasks
                    $this->template->tasks($project, $tasks);
                } ?>
            </td>
            <td>
                <?php if(isset($tests)) {
                    // Load Tasks
                    $this->template->tasks($project, $tests);
                } ?>
            </td>
            <td>
                <?php if(isset($done)) {
                    // Load Tasks
                    $this->template->tasks($project, $done);
                } ?>
            </td>
        </tr>

    </table>
    <?php } else { ?>
    <div class="notice">This project doesn't have any task.</div>
    <?php } ?>

Let’s use the different arrays with the tasks for each phase (which we included in the project.php controller) to display the tasks in different columns. If you visit the Dashboard and click in the title of a project, you’ll go into the Task Board and will get an error. This is happening because we need to update the Template library and create another library in the templates. Notice the call $this->template->tasks($project, $tests), which will load the view responsible for displaying each task.

Template

Open the file application/libraries/Template.php. Let’s add the following method:

    function tasks($project, $tasks)
    {
        // Get current CI Instance
        $CI = & get_instance();
                
        $i = 0;
        foreach ($tasks as $task) {
            $i++;
            // Load menu template
            $CI->load->view('template/single_task', array('i' => $i, 'project' => $project, 'task' => $task));
        }
    }

This method will loop the array of tasks for each phase and load a new template for each of them.

Single Task

Create a new file called application/views/template/single_task.php. The code will be the following:

<div id="task_<?php echo $task['id']; ?>" <?php if($task['status'] == 3) { ?>title="<?php echo $task['description']; ?>"<?php } ?>
        class="task <?php echo ($task['user'] == $current_user)?'my-task':'project-task'; ?>">
    <p class="task_id">#<?php echo $task['id']; ?></p>
    <p class="task_title"><?php echo anchor('task/edit/'.$project.'/'.$task['id'], $task['title']); ?></p>
    <p class="task_user">Assigned to: <?php echo $users[$task['user']]['email']; ?></p>
    <?php if($task['status'] < 3) { ?>
    <p class="task_text"><?php echo word_limiter($task['description'], 30); ?></p>
    <?php } ?>
    <?php if($task['status'] == 0) { ?>
    <p class="task_links"><?php echo anchor('task/move/'.$project.'/'.$task['id'].'/1', 'Start &raquo;'); ?></p>
    <?php } else if($task['status'] == 1) { ?>
    <p class="task_links">
        <?php echo anchor('task/move/'.$project.'/'.$task['id'].'/0', '&laquo; Back'); ?>
        |
        <?php echo anchor('task/move/'.$project.'/'.$task['id'].'/2', 'Test &raquo;'); ?>
    </p>
    <?php } else if($task['status'] == 2) { ?>
    <p class="task_links">
        <?php echo anchor('task/move/'.$project.'/'.$task['id'].'/1', '&laquo; Back'); ?>
        |
        <?php echo anchor('task/move/'.$project.'/'.$task['id'].'/3', 'Finish &raquo;'); ?>
    </p>
    <?php } else if($task['status'] == 3) { ?>
    <p class="task_links"><?php echo anchor('task/move/'.$project.'/'.$task['id'].'/2', '&laquo; Back'); ?></p>
    <?php } ?>
</div>

All the data about the task will be displayed in this view. Besides, in the end of the file, we have links to move the task to the next or to the previous phase. As the new tasks are always created with the status 0 (To Do), we can send it to the status 1. When a task is in status 1, we can send it back to 0 or forward it to 2… and so on.

CSS

We’ll finish this article with some styling for our Task Board. Paste the following code before the forms definitions (FORMS comment).

/* TASKS */
.task{
    margin:2px 0;
    padding:2px;
    background:#fff;
    position:relative;
    border:1px solid #D5D5D5
}
.task:hover{
    -moz-box-shadow:0 0 5px #999;
    -webkit-box-shadow:0 0 5px #999;
    box-shadow:0 0 5px #999
}
.task_id{margin:0;padding:1px;position:absolute;right:0;top:0}
.task_title{font-weight:bold;text-decoration:underline;margin:0;padding:1px;width:80%}
.task_text{margin:0;padding:1px}
.task_info{margin:0;padding:1px}
.task_links{text-align:center;margin:0;padding:1px}
.task_user{margin:2px 0;font-style:italic;color:#666;font-size:11px;}

Conclusion

Well, this is all that was left to finish the Simple Task Board as it is right now. This is an application that I’m planing to update soon. As I’ll keep it open source, keep track of the changes in the GitHub repository, as I’ll be upgrading the code created in this series of tutorials. Leave your comment!

Download the complete project here.



  • recent

    Hi it’s a good tuto a download the complete script and everything it’s ok, but i can’t
    Associated Users to a prajoct when i’am created or edit a project

    Thanks for replay:

  • Hello Oscar,

    Please update autoload array
    $autoload[‘libraries’] = array(‘database’,’template’,’session’,’usercontrol’);
    In git.
    Just checking your app.Good one so far.


    Alok Tiwari