Index: tasks.module
===================================================================
--- tasks.module (revision 1)
+++ tasks.module (working copy)
@@ -20,7 +20,11 @@
// Implementation of hook_perm().
function tasks_perm() {
- return array('create task', 'edit own task', 'edit all tasks', 'access tasks main page');
+ if(variable_get("tasks_use_timer", 0)>0) {
+ return array('create task', 'edit own task', 'edit all tasks', 'access tasks main page', 'edit times', 'edit own times', 'add times');
+ } else {
+ return array('create task', 'edit own task', 'edit all tasks', 'access tasks main page');
+ }
}
// Implementation of hook_access().
@@ -155,6 +159,14 @@
'#options' => $users
);
+ if(variable_get('tasks_use_timer', 0)) {
+ $form['time'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Timer')
+ );
+ $form['time']['timer'] = _tasks_timer_form($node);
+ }
+
$form['completed'] = array(
'#type' => 'checkbox',
'#title' => t('Completed?'),
@@ -211,7 +223,7 @@
// Implementation of hooks_forms_alter so we don't see preview or delete buttons for tasks
function tasks_form_alter($form_id, &$form) {
global $user;
-
+
if ($form_id == 'tasks_node_form') {
unset($form['preview']);
//unset($form['delete']);
@@ -240,8 +252,9 @@
$node->completed_date['month'] = "00";
$node->completed_date['day'] = "00";
}
-
- db_query("INSERT INTO {tasks} (nid, parent, assigned_to, order_by, completed) VALUES (%d, %d, %d, '%s', '%s')", $node->nid, $node->parent, $node->assigned_to, $node->order_by, $node->completed_date['year'].'-'.$node->completed_date['month'].'-'.$node->completed_date['day']);
+ $node->start = '0';
+ $node->stop = '0';
+ db_query("INSERT INTO {tasks} (nid, parent, assigned_to, order_by, completed, start, stop) VALUES (%d, %d, %d, '%s', '%s','%s','%s')", $node->nid, $node->parent, $node->assigned_to, $node->order_by, $node->completed_date['year'].'-'.$node->completed_date['month'].'-'.$node->completed_date['day'],$node->start,$node->stop);
_tasks_order_by($node);
}
@@ -255,8 +268,33 @@
$node->completed_date['month'] = "00";
$node->completed_date['day'] = "00";
}
-
- db_query("UPDATE {tasks} SET parent = %d, assigned_to = %d, order_by = '%s', completed = '%s' WHERE nid = %d", $node->parent, $node->assigned_to, $node->order_by, $node->completed_date['year'].'-'.$node->completed_date['month'].'-'.$node->completed_date['day'], $node->nid);
+ if(variable_get("tasks_use_timer", 0) > 0) {
+ $startNum = $node->timer['tasks_start_num'];
+ $stopNum = $node->timer['tasks_stop_num'];
+ $node->start = '';
+ $node->stop = '';
+ //print_r($node->timer);
+ if($node->timer[0]['start_date'] != 'Task not started' && $node->timer[0]['stop_date'] != 'Task not started') {
+ for($i = 0; $i < $startNum; $i++) {
+ if($node->timer[$i]['delete'] == 0) {
+ $node->start .= strtotime($node->timer[$i]['start_date']).',';
+ if($node->timer[$i]['stop_date'] != 'Running...') {
+ $node->stop .= strtotime($node->timer[$i]['stop_date']).',';
+ }
+ }
+ }
+ $node->start = rtrim($node->start,',');
+ $node->stop = rtrim($node->stop,',');
+ if($startNum - $stopNum == 0 && $node->completed != '0000-00-00') {
+ $node->stop = $node->stop.','._tasks_hours($node->start,$node->stop,$node->completed);
+ }
+ }
+ if($node->start == '' && $node->stop == '') {
+ $node->start = '0';
+ $node->stop = '0';
+ }
+ }
+ db_query("UPDATE {tasks} SET parent = %d, assigned_to = %d, order_by = '%s', completed = '%s', start = '%s', stop = '%s' WHERE nid = %d", $node->parent, $node->assigned_to, $node->order_by, $node->completed_date['year'].'-'.$node->completed_date['month'].'-'.$node->completed_date['day'],$node->start,$node->stop,$node->nid);
_tasks_order_by($node);
// Redirect to the tasks home page?
@@ -313,7 +351,28 @@
}
$node = node_prepare($node, $teaser);
-
+
+ //Get Task hours
+ if(variable_get("tasks_use_timer", 0)>0) {
+ $task = db_fetch_object(db_query("SELECT t.start, t.stop, t.completed FROM {tasks} t WHERE t.nid = %s", $node->nid));
+ if($_POST['edit']['tasks_stop_watch'] == 'start') {
+ if($task->start == 0) {
+ $task->start = time();
+ } else {
+ $task->start .= ','.time();
+ }
+ db_query("UPDATE {tasks} SET start = '%s' WHERE nid = %d",$task->start,$node->nid);
+ } else if($_POST['edit']['tasks_stop_watch'] == 'stop') {
+ if($task->stop == 0) {
+ $task->stop = time();
+ } else {
+ $task->stop .= ','.time();
+ }
+ db_query("UPDATE {tasks} SET stop = '%s' WHERE nid = %d",$task->stop,$node->nid);
+ }
+ $node->body .= _tasks_formated_time($task->start,$task->stop,$task->completed,1);
+ $node->body .= drupal_get_form('tasks_timer_clocker',_tasks_timer_stopwatch($task->start,$task->stop,$task->completed));
+ }
$output = '';
@@ -361,37 +420,78 @@
//$tasks_colour = drupal_unpack($task)->tasks_colour;
$extra = drupal_unpack($task);
$tasks_colour = $extra->tasks_colour;
+ $hours = 0;
$task = node_load(array('nid'=>$task->nid));
$rows[] = array(
'data' => array(
array('data' => $assigned_name, 'style' => "width:25px;".($tasks_colour ? "background:$tasks_colour;":'')),
- array('data' => l($task->title, "node/$task->nid", array('name'=>'task'.$task->nid)), 'style'=>($task->completed>0)?'text-decoration: line-through;':''),
- array('data' => ($task->completed>0)?$task->completed:'No'),
- array('data' => "nid');\">Expand ".l("
", "node/$task->nid/edit/home",array(),null,null,false,true).' '.l('Up',"node/$node->nid",array(),"action=up&task=$task->nid").' '.l('Down',"node/$node->nid",array(),"action=down&task=$task->nid")),
+ array('data' => l($task->title, "node/$task->nid", array('name'=>'task'.$task->nid)), 'style'=>($task->completed>0)?'text-decoration: line-through;':'')
)
);
+ // Add new row for hours
+ if(variable_get("tasks_use_timer", 0)>0) {
+ $hours = _tasks_hours($task->start,$task->stop,$task->completed);
+ if($hours > 0) {
+ $hours = "nid');\">".$hours."";
+ }
+ $rows[count($rows)-1]['data'][] = array('data' => $hours);
+ }
+ $rows[count($rows)-1]['data'][] = array('data' => ($task->completed>0)?$task->completed:'No');
+ $rows[count($rows)-1]['data'][] = array('data' => "nid');\">Expand ".l("
", "node/$task->nid/edit/home",array(),null,null,false,true).' '.l('Up',"node/$node->nid",array(),"action=up&task=$task->nid").' '.l('Down',"node/$node->nid",array(),"action=down&task=$task->nid"));
+
$task = node_prepare($task);
- $rows[] = array(
- 'data' => array(
- array('data' => $task->body, 'colspan' => '4'),
- ),
- 'class' => 'task-expand', 'id' => "row-$task->nid", 'style' => 'display:none;'
- );
+ if(variable_get("tasks_use_timer", 0)>0) {
+ // change last column span to 5
+ $rows[] = array(
+ 'data' => array(
+ array('data' => $task->body, 'colspan' => '5'),
+ ),
+ 'class' => 'task-expand', 'id' => "row-$task->nid", 'style' => 'display:none;'
+ );
+ // add new row for timer details if necessary
+ if($hours > 0) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => _tasks_formated_time($task->start,$task->stop,$task->completed), 'colspan' => '5'),
+ ),
+ 'class' => 'task-expand', 'id' => "row-timer-$task->nid", 'style' => 'display:none;'
+ );
+ }
+ $header = array(t('Assigned'),t('Task'),t('Hours'),t('Complete?'), t('Edit'));
+ } else {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => $task->body, 'colspan' => '4'),
+ ),
+ 'class' => 'task-expand', 'id' => "row-$task->nid", 'style' => 'display:none;'
+ );
+ $header = array(t('Assigned'),t('Task'),t('Complete?'), t('Edit'));
+ }
}
- $header = array(t('Assigned'),t('Task'), t('Complete?'), t('Edit'));
- $output .= theme('table', $header, $rows, array("id"=>"task-list"));
}
-
+ $output .= theme('table', $header, $rows, array("id"=>"task-list"));
$node->body .= $output;
}
}
+function tasks_settings() {
+ //record time spent on a task
+ $options = array('1' => t('Enabled'), '0' => t('Disabled'));
+ $form['tasks_use_timer'] = array(
+ '#type' => 'radios',
+ '#title' => t('Enable time spent'),
+ '#default_value' => variable_get('tasks_use_timer', 0),
+ '#options' => $options,
+ '#description' => t('Allows for time logging of a task')
+ );
+
+ return $form;
+}
-
// PRIVATE FUNCTIONS
@@ -449,4 +549,299 @@
db_query("UPDATE {tasks} SET order_by = %d WHERE nid = %d", $task->order_by, $task->nid);
}
-}
\ No newline at end of file
+}
+
+
+/*
+ FUNCTION _tasks_hours()
+
+ This function returns total hours worked on task
+
+
+*/
+
+function _tasks_hours($start, $stop,$complete = '0000-00-00') {
+ $startTimes = explode(',',$start);
+ $stopTimes = explode(',',$stop);
+ if($start == 0) {
+ $startNum = 0;
+ } else {
+ $startNum = count($startTimes);
+ }
+ if($stop == 0) {
+ $stopNum = 0;
+ } else {
+ $stopNum = count($stopTimes);
+ }
+ $totalTime = 0;
+ // For a complete task final stop time is total in unix time stamp
+ if($complete != '0000-00-00' && $stopNum - $startNum == 1) {
+ return $stopTimes[$stopNum-1];
+ // if there is at least on start time set the current hours
+ } else {
+ if($stopNum > 0) {
+ for($i=0;$i<$startNum-1;$i++) {
+ $totalTime = $totalTime+$stopTimes[$i]-$startTimes[$i];
+ }
+ }
+ if($startNum - $stopNum == 1) {
+ // If the last stop sign is not set, then use the current time for hours.
+ $totalTime = $totalTime+time()-$startTimes[$startNum-1];
+ } else if($startNum == $stopNum) {
+ $totalTime = $totalTime+$stopTimes[$stopNum-1]-$startTimes[$startNum-1];
+ }
+ // return hours
+ if($totalTime > 0) {
+ $totalTime = round((($totalTime/60)/60),2);
+ }
+ }
+ return $totalTime;
+}
+
+
+/*
+ FUNCTION _tasks_formated_time()
+
+ This function returns a table of Start and Stop times
+
+
+*/
+
+function _tasks_formated_time($start, $stop,$complete = '0000-00-00',$showTotal = 0) {
+ $startTimes = explode(',',$start);
+ $stopTimes = explode(',',$stop);
+ if($start == 0) {
+ $startNum = 0;
+ } else {
+ $startNum = count($startTimes);
+ }
+ if($stop == 0) {
+ $stopNum = 0;
+ } else {
+ $stopNum = count($stopTimes);
+ }
+
+ if($startNum > 0 && $startTimes[$startNum-1] != 0) {
+ if($stopNum > 0) {
+ for($i=0;$i<$startNum-1;$i++) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => _tasks_date('g:ia n/j/y',$startTimes[$i]), 'style' => "width:25px"),
+ array('data' => _tasks_date('g:ia n/j/y',$stopTimes[$i]), 'style' => "width:25px"),
+ )
+ );
+ }
+ }
+ if($startNum > $stopNum) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => _tasks_date('g:ia n/j/y',$startTimes[$startNum-1]), 'style' => "width:25px"),
+ array('data' => 'Still Running', 'style' => "width:25px"),
+ )
+ );
+ } else if($startNum < $stopNum && $complete) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => _tasks_date('g:ia n/j/y',$startTimes[$startNum-1]), 'style' => "width:25px"),
+ array('data' => _tasks_date('g:ia n/j/y',$stopTimes[$stopNum-2]), 'style' => "width:25px"),
+ )
+ );
+ } else if ($startNum == $stopNum) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => _tasks_date('g:ia n/j/y',$startTimes[$startNum-1]), 'style' => "width:25px"),
+ array('data' => _tasks_date('g:ia n/j/y',$stopTimes[$stopNum-1]), 'style' => "width:25px"),
+ )
+ );
+ }
+ if($showTotal > 0) {
+ $rows[] = array(
+ 'data' => array(
+ array('data' => 'Total Time (hrs)', 'style' => "width:25px"),
+ array('data' => _tasks_hours($start,$stop,$complete), 'style' => "width:25px"),
+ )
+ );
+ }
+ $header = array(t('Start'),t('Stop'));
+ return theme('table', $header, $rows, array("id"=>"time-list"));
+ }
+}
+
+function _tasks_timer_stopwatch($start, $stop,$complete = '0000-00-00') {
+ if (user_access('add times')) {
+ $startTimes = explode(',',$start);
+ $stopTimes = explode(',',$stop);
+ if($start == 0) {
+ $startNum = 0;
+ } else {
+ $startNum = count($startTimes);
+ }
+ if($stop == 0) {
+ $stopNum = 0;
+ } else {
+ $stopNum = count($stopTimes);
+ }
+
+ if($complete == '0000-00-00') {
+ if($startNum > $stopNum) {
+ $form['tasks_stop_watch'] = array(
+ '#type' => 'hidden',
+ '#value' => 'stop'
+ );
+ $form['timer'] = array(
+ '#type' => 'submit',
+ '#value' => t('Stop Timer')
+ );
+ } else {
+ $form['tasks_stop_watch'] = array(
+ '#type' => 'hidden',
+ '#value' => 'start'
+ );
+ $form['timer'] = array(
+ '#type' => 'submit',
+ '#value' => t('Start Timer'.$node->start)
+ );
+ }
+ //$form['#action'] = "node/$node->nid";
+ return $form;
+ }
+ }
+}
+
+function _tasks_timer_form($node) {
+ global $user;
+ $form['#type'] = 'item';
+ $form['#tree'] = TRUE;
+ $form['#theme'] = 'tasks_timer_form';
+ $editable = FALSE;
+
+ if ((user_access('edit own times') && ($user->uid == $node->uid)) || user_access('edit times')) {
+ $editable = TRUE;
+ }
+
+ if($editable && $node->nid) {
+ $form['#description'] = t('Edit Start and Stop Times (HH:MM MM/DD/YYYY) or remove entries');
+ } else {
+ $form['#description'] = t('Start and Stop Times');
+ }
+ if($node->nid) {
+ $task = db_fetch_object(db_query("SELECT t.start, t.stop, t.completed FROM {tasks} t WHERE t.nid = %s", $node->nid));
+ } else {
+ $task = array('start' => 0,'stop' => 0,'completed' => 0);
+ }
+ $startTimes = explode(',',$task->start);
+ $stopTimes = explode(',',$task->stop);
+ if($task->start == 0) {
+ $startNum = 0;
+ } else {
+ $startNum = count($startTimes);
+ }
+ if($task->stop == 0) {
+ $stopNum = 0;
+ } else {
+ $stopNum = count($stopTimes);
+ }
+
+ if($startNum > 0) {
+ for($i=0;$i<$startNum;$i++) {
+ $form[$i]['start_date'] = array(
+ '#type' => 'textfield',
+ '#default_value' => _tasks_date('H:i n/j/y',$startTimes[$i]),
+ '#size' => 19,
+ '#maxlength' => 19,
+ );
+ $form[$i]['stop_date'] = array(
+ '#type' => 'textfield',
+ '#size' => 19,
+ '#maxlength' => 19
+ );
+ $form[$i]['delete'] = array(
+ '#type' => 'checkbox',
+ '#default_value' => 0
+ );
+ if(!$editable) {
+ $form[$i]['start_date']['#attributes'] = array('disabled' => 'disabled');
+ $form[$i]['stop_date']['#attributes'] = array('disabled' => 'disabled');
+ $form[$i]['delete']['#attributes'] = array('disabled' => 'disabled');
+ }
+
+ if($i == $startNum-1 && $startNum > $stopNum) {
+ $form[$i]['stop_date']['#default_value'] = 'Running...';
+ $form[$i]['stop_date']['#attributes'] = array('disabled' => 'disabled');
+ } else {
+ $form[$i]['stop_date']['#default_value'] = _tasks_date('H:i n/j/y',$stopTimes[$i]);
+ }
+ }
+ } else {
+ $form[0]['start_date'] = array(
+ '#type' => 'textfield',
+ '#default_value' => 'Task not started',
+ '#attributes' => array('disabled' => 'disabled'),
+ '#size' => 19,
+ '#maxlength' => 19,
+ );
+ $form[0]['stop_date'] = array(
+ '#type' => 'textfield',
+ '#default_value' => 'Task not started',
+ '#attributes' => array('disabled' => 'disabled'),
+ '#size' => 19,
+ '#maxlength' => 19,
+ );
+ }
+ $form['tasks_start_num'] = array(
+ '#type' => 'hidden',
+ '#value' => $startNum
+ );
+ $form['tasks_stop_num'] = array(
+ '#type' => 'hidden',
+ '#value' => $stopNum
+ );
+ return $form;
+}
+
+function theme_tasks_timer_form(&$form) {
+ $header = array(t('Start'), t('Stop'), t('Delete'));
+ foreach (element_children($form) as $key) {
+ $row = array();
+ $row[] = form_render($form[$key]['start_date']);
+ $row[] = form_render($form[$key]['stop_date']);
+ $row[] = form_render($form[$key]['delete']);
+ $rows[]['data'] = $row;
+ }
+ $output = theme('table', $header, $rows);
+ $output .= form_render($form);
+
+ return $output;
+}
+
+/*
+ FUNCTION _tasks_date()
+
+ This function returns a formated time with timezone
+
+
+*/
+
+function _tasks_date($format, $timestamp, $offset = null) {
+ global $user;
+
+ if (isset($offset)) {
+ $timestamp += $offset;
+ }
+ elseif (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
+ $timestamp += $user->timezone;
+ }
+ else {
+ $timestamp += variable_get('date_default_timezone', 0);
+ }
+
+ // make sure we apply the site first day of the week setting for dow requests
+ if ($format == 'w') {
+ $result = _event_day_of_week($timestamp);
+ }
+ else {
+ $result = gmdate($format, $timestamp);
+ }
+ return $result;
+}
+