'. t('Here you can set up parameters for Storm-Quick-TimeTracker.') .'

'; case 'admin/help#storm_quicktt': return filter_filter('process', 2, NULL, file_get_contents(dirname(__FILE__) ."/README.txt")); } } /** * Implementation of hook_menu(). */ function storm_quicktt_menu() { $items = array(); $access_config = array('administer site configuration'); $items['admin/settings/storm/quicktt'] = array( 'title' => 'Storm Quick TimeTracker', 'description' => 'Configure Storm Quick TimeTracker', 'page callback' => 'drupal_get_form', 'page arguments' => array('storm_quicktt_settings'), 'access arguments' => $access_config, 'type' => MENU_LOCAL_TASK, 'file' => 'storm_quicktt.admin.inc', ); $items['stormquicktt/interact'] = array( 'page callback' => 'storm_quicktt_interact', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } function storm_quicktt_add_resources() { static $loaded = FALSE; if (!$loaded) { drupal_add_css(drupal_get_path('module', 'storm_quicktt') .'/storm_quicktt.css'); drupal_add_js(drupal_get_path('module', 'storm_quicktt') .'/storm_quicktt.js'); drupal_add_js(drupal_get_path('module', 'storm_quicktt') .'/jquery.timers.js'); drupal_add_js(array('storm_quicktt_url' => url('stormquicktt/interact', array('absolute' => TRUE,))), 'setting'); $loaded = TRUE; } } /** * Implementation of hook_block(). */ function storm_quicktt_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $blocks[0]['info'] = t('Storm Quick TimeTracker'); $blocks[0]['cache'] = BLOCK_NO_CACHE; return $blocks; case 'configure': return; case 'save': return; case 'view': if (!user_access('Storm timetracking: add')) { return; } storm_quicktt_add_resources(); $v = variable_get('storm_quicktt_project_stati', array('in progress')); $sql = "SELECT n.*, spr.* FROM {node} AS n INNER JOIN {stormproject} AS spr ON n.vid=spr.vid WHERE n.status=1 AND n.type='stormproject' AND (spr.projectstatus IN ('". implode("','", $v) ."')) ORDER BY spr.organization_title, n.title"; $sql = stormproject_access_sql($sql); $result = db_query($sql); $options = array('0' => '- No billable work -'); while ($node = db_fetch_object($result)) { if (!isset($options[$node->organization_title])) { $options[$node->organization_title] = array(); } $options[$node->organization_title][$node->nid] = $node->title; } $form = drupal_get_form('storm_quicktt_blockform', $options); $blocks['subject'] = t('Quick Timetracking'); $blocks['content'] = << $form EOT; return $blocks; } } function storm_quicktt_blockform($form_state, $options) { $nid = storm_quicktt_tracking_active_nid(); $pid = isset($_SESSION['storm_quicktt_pid']) ? $_SESSION['storm_quicktt_pid'] : 0; if (!empty($nid) && empty($pid)) { switch(storm_quicktt_tracking_active_type()) { case 'prj': $pid = $nid; break; case 'tkt': case 'tsk': $node = node_load($nid); if (!empty($node) && !empty($node->project_nid)) { $pid = $node->project_nid; $_SESSION['storm_quicktt_pid'] = $pid; } break; } } $mode = isset($_SESSION['storm_quicktt_mode']) ? $_SESSION['storm_quicktt_mode'] : TRUE; $form = array(); $form['#cache'] = TRUE; $form['selects'] = array( '#tree' => TRUE, '#prefix' => '
', '#suffix' => '
', ); $form['selects']['mode'] = array( '#type' => 'checkbox', '#title' => t('Auto-Start Tracking'), '#default_value' => $mode, ); $form['selects']['projects'] = array( '#type' => 'select', '#title' => t('Projects'), '#options' => $options, '#default_value' => $pid, '#size' => 10, ); if (!module_exists('storm_dashboard')) { $form['selects']['info'] = array( '#tree' => TRUE, '#prefix' => '
', '#suffix' => '
', ); $form['selects']['info']['time'] = array( '#type' => 'markup', '#value' => storm_quicktt_tracking_info(), ); } return $form; } function storm_quicktt_interact() { if (!isset($_POST['op'])) { exit; } $_GET['q'] = $_SERVER['HTTP_REFERER']; $op = $_POST['op']; $nid = $_POST['nid']; $_SESSION['storm_quicktt_mode'] = ($_POST['mode'] == 'true'); switch ($op) { case 'pause': storm_quicktt_pause_time(); print 'OK'; break; case 'resume': storm_quicktt_resume_time(); print 'OK'; break; case 'update': if (!$_SESSION['storm_quicktt_update_active']) { $_SESSION['storm_quicktt_update_active'] = TRUE; print storm_quicktt_elapsed_time(); $_SESSION['storm_quicktt_update_active'] = FALSE; } else { print 'OK'; } break; case 'note': storm_quicktt_note_for_time($nid); print 'OK'; break; case 'triggerTimetracking': $oid = 0; $pid = 0; $tid = 0; $kid = 0; $y = explode('-', $nid); $nid = $y[2]; if (!storm_quicktt_tracking_active() || storm_quicktt_tracking_active_nid() != $nid) { $node = node_load($nid); switch ($node->type) { case 'stormticket': $kid = $nid; $pid = $node->project_nid; break; case 'stormtask': $tid = $nid; $pid = $node->project_nid; break; case 'stormproject': $pid = $nid; break; case 'stormorganization': $oid = $nid; break; } } $msg = storm_quicktt_start($oid, $pid, $tid, $kid, FALSE); $trigger = storm_quicktt_timetracking_trigger($nid); $msg .= storm_quicktt_tracking_info(); print drupal_json(array('msg' => $msg, 'pid' => $pid, 'trigger' => $trigger)); break; default: $msg = ""; if ($_SESSION['storm_quicktt_mode']) { $msg = storm_quicktt_start(0, $nid, 0, 0, FALSE); print $msg . storm_quicktt_tracking_info(); } elseif ($nid) { $pid = isset($_SESSION['storm_quicktt_pid']) ? $_SESSION['storm_quicktt_pid'] : 0; if ($pid == $nid) { print $msg . storm_quicktt_tracking_info(); } else { $title = t('Action'); $link = l(t('Goto Project'), 'node/'. $nid); $msg .= '
'. $link . '
'; $msg .= storm_quicktt_timetracking_trigger($nid); $active_nid = storm_quicktt_tracking_active_nid(); if ($active_nid) { $msg .= storm_quicktt_tracking_info(); } print $msg; } } else { $active_nid = storm_quicktt_tracking_active_nid(); if ($active_nid) { $msg .= storm_quicktt_tracking_info(); } print $msg; } break; } exit; } function storm_quicktt_start($oid = 0, $pid = 0, $tid = 0, $kid = 0, $show_msg = TRUE) { $start = time(); $msg = ""; if ($_SESSION['storm_quicktt_oid']) { $msg = storm_quicktt_store_time($start, $show_msg); } $_SESSION['storm_quicktt_note_for_time'] = ''; if ($kid) { //Ticket-ID is set and we get the other IDs from the node $node = node_load($kid); $node->ticket_nid = $node->nid; } elseif ($tid) { //Task-ID is set and we get the other IDs from the node $node = node_load($tid); $node->task_nid = $node->nid; } elseif ($pid) { //Project-ID is set and we get the other IDs from the node $node = node_load($pid); $node->project_nid = $node->nid; } elseif ($oid) { //Organization-ID is set and we get the other IDs from the node $node = node_load($oid); $node->organization_nid = $node->nid; } else { //No ID is set and we do only store time if a timetracking was active $node = new stdClass(); } $_SESSION['storm_quicktt_oid'] = (isset($node->organization_nid)) ? $node->organization_nid : 0; $_SESSION['storm_quicktt_pid'] = (isset($node->project_nid)) ? $node->project_nid : 0; $_SESSION['storm_quicktt_tid'] = (isset($node->task_nid)) ? $node->task_nid : 0; $_SESSION['storm_quicktt_kid'] = (isset($node->ticket_nid)) ? $node->ticket_nid : 0; $_SESSION['storm_quicktt_start'] = (isset($node->organization_nid)) ? $start : 0; $_SESSION['storm_quicktt_pause_start'] = 0; $_SESSION['storm_quicktt_pause_collect'] = 0; return $msg; } function storm_quicktt_pause_time() { if (!storm_quicktt_tracking_active()) { return; } if (!empty($_SESSION['storm_quicktt_pause_start'])) { return; } if (variable_get('storm_quicktt_pause_split', FALSE)) { $oid = $_SESSION['storm_quicktt_oid']; $pid = $_SESSION['storm_quicktt_pid']; $tid = $_SESSION['storm_quicktt_tid']; $kid = $_SESSION['storm_quicktt_kid']; $start = $_SESSION['storm_quicktt_start']; storm_quicktt_store_time(time(), FALSE); $_SESSION['storm_quicktt_oid'] = $oid; $_SESSION['storm_quicktt_pid'] = $pid; $_SESSION['storm_quicktt_tid'] = $tid; $_SESSION['storm_quicktt_kid'] = $kid; $_SESSION['storm_quicktt_start'] = $start; } $_SESSION['storm_quicktt_pause_start'] = time(); } function storm_quicktt_resume_time() { if (empty($_SESSION['storm_quicktt_pause_start'])) { return; } if (variable_get('storm_quicktt_pause_split', FALSE)) { $_SESSION['storm_quicktt_pause_collect'] += ($_SESSION['storm_quicktt_pause_start'] - $_SESSION['storm_quicktt_start']); $_SESSION['storm_quicktt_start'] = time(); } else { $_SESSION['storm_quicktt_pause_collect'] += (time() - $_SESSION['storm_quicktt_pause_start']); } $_SESSION['storm_quicktt_pause_start'] = 0; } function storm_quicktt_elapsed_time() { if (!empty($_SESSION['storm_quicktt_pause_start']) && variable_get('storm_quicktt_pause_split', FALSE)) { if (!empty($_SESSION['storm_quicktt_start'])) { return '
'. t('Elapsed time: !time min', array('!time' => floor(($_SESSION['storm_quicktt_pause_start'] - $_SESSION['storm_quicktt_start']) / 60))) .'
'; } return ''; } storm_quicktt_store_time(); if (!empty($_SESSION['storm_quicktt_ttid'])) { $now = time(); if (variable_get('storm_quicktt_pause_split', FALSE) && !empty($_SESSION['storm_quicktt_pause_collect'])) { $now += $_SESSION['storm_quicktt_pause_collect']; } return '
'. t('Elapsed time: !time min', array('!time' => floor(($now - $_SESSION['storm_quicktt_start']) / 60))) .'
'; } else { return ''; } } function storm_quicktt_store_time($stop = 0, $show_msg = TRUE) { if (!user_access('Storm timetracking: add')) { return t('You have no permission to add timetracking.'); } global $user; $oid = $_SESSION['storm_quicktt_oid']; $pid = $_SESSION['storm_quicktt_pid']; $tid = $_SESSION['storm_quicktt_tid']; $kid = $_SESSION['storm_quicktt_kid']; $start = $_SESSION['storm_quicktt_start']; $pause = 0; if ($stop) { storm_quicktt_resume_time(); $pause = $_SESSION['storm_quicktt_pause_collect']; if (variable_get('storm_quicktt_pause_split', FALSE)) { $pause = 0; } unset($_SESSION['storm_quicktt_oid']); unset($_SESSION['storm_quicktt_pid']); unset($_SESSION['storm_quicktt_tid']); unset($_SESSION['storm_quicktt_kid']); unset($_SESSION['storm_quicktt_start']); } if ($oid) { $finish = ($stop) ? $stop : time(); $minutes = ceil(($finish-$start) / 60); if ($minutes >= variable_get('storm_quicktt_mintime2record', 5)) { if ($kid) { $type = t('Ticket'); $node = node_load($kid); $name = $node->title; } elseif ($tid) { $type = t('Task'); $node = node_load($tid); $name = $node->title; } elseif ($pid) { $type = t('Project'); $node = node_load($pid); $name = $node->title; } elseif ($oid) { $type = t('Organization'); $node = node_load($oid); $name = $node->title; } if (!isset($_SESSION['storm_quicktt_ttid'])) { $node = new stdClass(); $node->uid = $user->uid; $node->type = 'stormtimetracking'; $node->title = $name .' ('. variable_get('storm_quicktt_default_title', 'Auto-created by QuickTT') .')'; $node->organization_nid = $oid; $node->project_nid = $pid; $node->task_nid = $tid; $node->ticket_nid = $kid; $node->trackingdate = $start; $node->timebegin = format_date($start, 'custom', 'H:i'); $node->billable = variable_get('stormtimetracking_billable_default', FALSE); $node->billed = FALSE; } else { $node = node_load($_SESSION['storm_quicktt_ttid']); } $node->revision = FALSE; $node->timeend = format_date($finish, 'custom', 'H:i'); _stormtimetracking_beforesave($node); $old_stormtimetracking_auto_duration = variable_get('stormtimetracking_auto_duration', TRUE); variable_set('stormtimetracking_auto_duration', FALSE); $node->billing_duration = $node->duration - ($pause / 3600); if (empty($_SESSION['storm_quicktt_note_for_time']) OR empty($node->body)) { $pos = FALSE; } else { $pos = strpos($_SESSION['storm_quicktt_note_for_time'], $node->body); } if ($pos === FALSE) { $node->body .= $_SESSION['storm_quicktt_note_for_time']; } else { $node->body = $_SESSION['storm_quicktt_note_for_time']; } $_SESSION['storm_quicktt_note_for_time'] = $node->body; node_save($node); variable_set('stormtimetracking_auto_duration', $old_stormtimetracking_auto_duration); if ($stop) { unset($_SESSION['storm_quicktt_ttid']); } else { $_SESSION['storm_quicktt_ttid'] = $node->nid; return ''; } $destination = ($_GET['q'] == 'stormdashboard/interact') ? 'stormdashboard' : $_GET['q']; $link = l('edit', 'node/'. $node->nid .'/edit', array('query' => array('destination' => $destination))); $msg = t('Time spent on %type %name: %min minutes (!edit).', array('%type' => $type, '%name' => $name, '%min' => $minutes, '!edit' => $link)); } elseif (!$stop) { return ''; } else { $msg = t('Time spent too short and not recorded.'); } } drupal_get_messages(); //Clear messages to display only the following one. if ($show_msg) { drupal_set_message($msg); } $_SESSION['storm_quicktt_pause_start'] = 0; $_SESSION['storm_quicktt_pause_collect'] = 0; return '
'. $msg .'
'; } function storm_quicktt_note_for_time($text) { $_SESSION['storm_quicktt_note_for_time'] .= "

". $text ."

\n"; } function storm_quicktt_tracking_active_nid() { if (!storm_quicktt_tracking_active()) { return 0; } $oid = $_SESSION['storm_quicktt_oid']; $pid = $_SESSION['storm_quicktt_pid']; $tid = $_SESSION['storm_quicktt_tid']; $kid = $_SESSION['storm_quicktt_kid']; if ($kid) { //Ticket-ID is set and we get the other IDs from the node return $kid; } elseif ($tid) { //Task-ID is set and we get the other IDs from the node return $tid; } elseif ($pid) { //Project-ID is set and we get the other IDs from the node return $pid; } elseif ($oid) { //Organization-ID is set and we get the other IDs from the node return $oid; } else { //No ID is set which shouldn't be possible return 0; } } function storm_quicktt_tracking_active_type() { if (!storm_quicktt_tracking_active()) { return NULL; } $oid = $_SESSION['storm_quicktt_oid']; $pid = $_SESSION['storm_quicktt_pid']; $tid = $_SESSION['storm_quicktt_tid']; $kid = $_SESSION['storm_quicktt_kid']; if ($kid) { //Ticket-ID is set and we get the other IDs from the node return 'tkt'; } elseif ($tid) { //Task-ID is set and we get the other IDs from the node return 'tsk'; } elseif ($pid) { //Project-ID is set and we get the other IDs from the node return 'prj'; } elseif ($oid) { //Organization-ID is set and we get the other IDs from the node return 'org'; } else { //No ID is set which shouldn't be possible return NULL; } } function storm_quicktt_tracking_active() { return !empty($_SESSION['storm_quicktt_oid']); } function storm_quicktt_tracking_start() { return storm_quicktt_tracking_active() ? $_SESSION['storm_quicktt_start'] : 0; } function storm_quicktt_tracking_info() { $output = ''; if (storm_quicktt_tracking_active()) { $oid = $_SESSION['storm_quicktt_oid']; $pid = $_SESSION['storm_quicktt_pid']; $tid = $_SESSION['storm_quicktt_tid']; $kid = $_SESSION['storm_quicktt_kid']; $start = $_SESSION['storm_quicktt_start']; if ($kid) { //Ticket-ID is set and we get the other IDs from the node $node = node_load($kid); $type = t('Ticket'); } elseif ($tid) { //Task-ID is set and we get the other IDs from the node $node = node_load($tid); $type = t('Task'); } elseif ($pid) { //Project-ID is set and we get the other IDs from the node $node = node_load($pid); $type = t('Project'); } elseif ($oid) { //Organization-ID is set and we get the other IDs from the node $node = node_load($oid); $type = t('Organization'); } else { //No ID is set which shouldn't be possible return '
'. t('An error occured.') .'
'; } $output .= '
'. t('Started !time', array('!time' => storm_quicktt_start_link())) .'
'; $output .= '
'. t('Timetracking is active for %type !title.', array('%type' => $type, '!title' => l($node->title, 'node/'.$node->nid))) .'
'; $output .= '
'. t('Take a note: !noteform', array('!noteform' => storm_quicktt_noteform())) .'
'; } else { $output .= '
'. t('Currently not tracking any time.') .'
'; } $output .= ''; return $output; } function storm_quicktt_start_link() { if (!empty($_SESSION['storm_quicktt_kid'])) { $nid = $_SESSION['storm_quicktt_kid']; } elseif (!empty($_SESSION['storm_quicktt_tid'])) { $nid = $_SESSION['storm_quicktt_tid']; } elseif (!empty($_SESSION['storm_quicktt_pid'])) { $nid = $_SESSION['storm_quicktt_pid']; } elseif (!empty($_SESSION['storm_quicktt_oid'])) { $nid = $_SESSION['storm_quicktt_oid']; } if (!empty($nid)) { if (!empty($_SESSION['storm_quicktt_pause_start'])) { $style_pause = ' style="display:none"'; $style_resume = ''; } else { $style_pause = ''; $style_resume = ' style="display:none"'; } $text_paused = ''. t('Paused') .''; $path = drupal_get_path('module', 'storm'); $title_pause = t('Pause'); $title_resume = t('Resume'); $text = '
'. format_date($_SESSION['storm_quicktt_start']) .'
'; $text .= '
'. storm_quicktt_elapsed_time() .''. $text_paused .'
'; $text .= ''. $title_pause .''; $text .= ''. $title_resume .''; $text .= storm_quicktt_timetracking_trigger($nid, FALSE); return $text; } return format_date(time()); } function storm_quicktt_noteform() { return '
'; } /** * Returns the sanitized clickable icon to start/stop time tracking */ function storm_quicktt_timetracking_trigger($nid = 0, $info = TRUE) { if (!user_access('Storm timetracking: add')) { return ''; } storm_quicktt_add_resources(); $active = FALSE; if (!empty($nid) && storm_quicktt_tracking_active() && storm_quicktt_tracking_active_nid() == $nid) { $active = TRUE; } if (!$active) { $title = t('Start time tracking.'); $img_src = url(drupal_get_path('module', 'storm') .'/images/timetrackings.png', array('absolute' => TRUE)); $class = ""; $info_txt = ' '.t('Click to start timetracking'); } else { $title = t('Stop time tracking.'); $img_src = url(variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons') .'/dialog_close.png', array('absolute' => TRUE)); $class = "timetracking-active"; $info_txt = ' '.t('Click to stop timetracking'); } if (!$info) { $info_txt = ''; } return ''. ''. $title .''. '' . $info_txt . ''; } function storm_quicktt_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { if (!in_array($node->type, array('stormproject', 'stormorganization', 'stormtask', 'stormticket')) || !user_access('Storm timetracking: add')) { return; } if ($op == 'view') { $node->content['links']['storm_quicktt_timetracking_trigger'] = array( '#value' => storm_quicktt_timetracking_trigger($node->nid), '#weight' => 10, ); } }