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

'; } } /** * Implementation of hook_menu(). */ function stormquicktt_menu() { $items = array(); $access_config = array('administer site configuration'); $items['admin/settings/suitedesk/quicktt'] = array( 'title' => 'SuiteDesk Quick TimeTracker', 'description' => 'Configure SuiteDesk Quick TimeTracker', 'page callback' => 'drupal_get_form', 'page arguments' => array('stormquicktt_settings'), 'access arguments' => $access_config, 'type' => MENU_LOCAL_TASK, 'file' => 'stormquicktt.admin.inc', ); $items['stormquicktt/interact'] = array( 'page callback' => 'stormquicktt_interact', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } function stormquicktt_add_resources() { static $loaded = FALSE; if (!$loaded) { drupal_add_css(drupal_get_path('module', 'stormquicktt') .'/stormquicktt.css'); drupal_add_js(drupal_get_path('module', 'stormquicktt') .'/stormquicktt.js'); drupal_add_js(drupal_get_path('module', 'stormquicktt') .'/jquery.timers.js'); drupal_add_js(array('stormquicktt_url' => url('stormquicktt/interact', array('absolute' => TRUE,))), 'setting'); $loaded = TRUE; } } /** * Implementation of hook_block(). */ function stormquicktt_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $blocks[0]['info'] = t('SuiteDesk 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; } stormquicktt_add_resources(); $v = variable_get('stormquicktt_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' => t('- 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('stormquicktt_blockform', $options); $blocks['subject'] = t('Quick Timetracking'); $blocks['content'] = << $form EOT; return $blocks; } } function stormquicktt_blockform($form_state, $options) { $nid = stormquicktt_tracking_active_nid(); $pid = isset($_SESSION['stormquicktt_pid']) ? $_SESSION['stormquicktt_pid'] : 0; if (!empty($nid) && empty($pid)) { switch(stormquicktt_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['stormquicktt_pid'] = $pid; } break; } } $mode = isset($_SESSION['stormquicktt_mode']) ? $_SESSION['stormquicktt_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' => stormquicktt_tracking_info(), ); } return $form; } function stormquicktt_interact() { if (!isset($_POST['op'])) { exit; } $_GET['q'] = $_SERVER['HTTP_REFERER']; $op = $_POST['op']; $nid = $_POST['nid']; $_SESSION['stormquicktt_mode'] = ($_POST['mode'] == 'true'); switch ($op) { case 'pause': stormquicktt_pause_time(); print 'OK'; break; case 'resume': stormquicktt_resume_time(); print 'OK'; break; case 'update': if (!$_SESSION['stormquicktt_update_active']) { $_SESSION['stormquicktt_update_active'] = TRUE; print stormquicktt_elapsed_time(); $_SESSION['stormquicktt_update_active'] = FALSE; } else { print 'OK'; } break; case 'note': stormquicktt_note_for_time($nid); print 'OK'; break; case 'triggerTimetracking': $oid = 0; $pid = 0; $tid = 0; $kid = 0; $y = explode('-', $nid); $nid = $y[2]; if (!stormquicktt_tracking_active() || stormquicktt_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 = stormquicktt_start($oid, $pid, $tid, $kid, FALSE); $trigger = stormquicktt_timetracking_trigger($nid); $msg .= stormquicktt_tracking_info(); print drupal_json(array('msg' => $msg, 'pid' => $pid, 'trigger' => $trigger)); break; default: $msg = ""; if ($_SESSION['stormquicktt_mode']) { $msg = stormquicktt_start(0, $nid, 0, 0, FALSE); print $msg . stormquicktt_tracking_info(); } elseif ($nid) { $pid = isset($_SESSION['stormquicktt_pid']) ? $_SESSION['stormquicktt_pid'] : 0; if ($pid == $nid) { print $msg . stormquicktt_tracking_info(); } else { $title = t('Action'); $link = l(t('Goto Project'), 'node/'. $nid); $msg .= '
'. $link . '
'; $msg .= stormquicktt_timetracking_trigger($nid); $active_nid = stormquicktt_tracking_active_nid(); if ($active_nid) { $msg .= stormquicktt_tracking_info(); } print $msg; } } else { $active_nid = stormquicktt_tracking_active_nid(); if ($active_nid) { $msg .= stormquicktt_tracking_info(); } print $msg; } break; } exit; } function stormquicktt_start($oid = 0, $pid = 0, $tid = 0, $kid = 0, $show_msg = TRUE) { $start = time(); $msg = ""; if ($_SESSION['stormquicktt_oid']) { $msg = stormquicktt_store_time($start, $show_msg); } $_SESSION['stormquicktt_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['stormquicktt_oid'] = (isset($node->organization_nid)) ? $node->organization_nid : 0; $_SESSION['stormquicktt_pid'] = (isset($node->project_nid)) ? $node->project_nid : 0; $_SESSION['stormquicktt_tid'] = (isset($node->task_nid)) ? $node->task_nid : 0; $_SESSION['stormquicktt_kid'] = (isset($node->ticket_nid)) ? $node->ticket_nid : 0; $_SESSION['stormquicktt_start'] = (isset($node->organization_nid)) ? $start : 0; $_SESSION['stormquicktt_pause_start'] = 0; $_SESSION['stormquicktt_pause_collect'] = 0; return $msg; } function stormquicktt_pause_time() { if (!stormquicktt_tracking_active()) { return; } if (!empty($_SESSION['stormquicktt_pause_start'])) { return; } if (variable_get('stormquicktt_pause_split', FALSE)) { $oid = $_SESSION['stormquicktt_oid']; $pid = $_SESSION['stormquicktt_pid']; $tid = $_SESSION['stormquicktt_tid']; $kid = $_SESSION['stormquicktt_kid']; $start = $_SESSION['stormquicktt_start']; stormquicktt_store_time(time(), FALSE); $_SESSION['stormquicktt_oid'] = $oid; $_SESSION['stormquicktt_pid'] = $pid; $_SESSION['stormquicktt_tid'] = $tid; $_SESSION['stormquicktt_kid'] = $kid; $_SESSION['stormquicktt_start'] = $start; } $_SESSION['stormquicktt_pause_start'] = time(); } function stormquicktt_resume_time() { if (empty($_SESSION['stormquicktt_pause_start'])) { return; } if (variable_get('stormquicktt_pause_split', FALSE)) { $_SESSION['stormquicktt_pause_collect'] += ($_SESSION['stormquicktt_pause_start'] - $_SESSION['stormquicktt_start']); $_SESSION['stormquicktt_start'] = time(); } else { $_SESSION['stormquicktt_pause_collect'] += (time() - $_SESSION['stormquicktt_pause_start']); } $_SESSION['stormquicktt_pause_start'] = 0; } function stormquicktt_elapsed_time() { if (!empty($_SESSION['stormquicktt_pause_start']) && variable_get('stormquicktt_pause_split', FALSE)) { if (!empty($_SESSION['stormquicktt_start'])) { return '
'. t('Elapsed time: !time min', array('!time' => floor(($_SESSION['stormquicktt_pause_start'] - $_SESSION['stormquicktt_start']) / 60))) .'
'; } return ''; } stormquicktt_store_time(); if (!empty($_SESSION['stormquicktt_ttid'])) { $now = time(); if (variable_get('stormquicktt_pause_split', FALSE) && !empty($_SESSION['stormquicktt_pause_collect'])) { $now += $_SESSION['stormquicktt_pause_collect']; } return '
'. t('Elapsed time: !time min', array('!time' => floor(($now - $_SESSION['stormquicktt_start']) / 60))) .'
'; } else { return ''; } } function stormquicktt_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['stormquicktt_oid']; $pid = $_SESSION['stormquicktt_pid']; $tid = $_SESSION['stormquicktt_tid']; $kid = $_SESSION['stormquicktt_kid']; $start = $_SESSION['stormquicktt_start']; $pause = 0; if ($stop) { stormquicktt_resume_time(); $pause = $_SESSION['stormquicktt_pause_collect']; if (variable_get('stormquicktt_pause_split', FALSE)) { $pause = 0; } unset($_SESSION['stormquicktt_oid']); unset($_SESSION['stormquicktt_pid']); unset($_SESSION['stormquicktt_tid']); unset($_SESSION['stormquicktt_kid']); unset($_SESSION['stormquicktt_start']); } if ($oid) { $finish = ($stop) ? $stop : time(); $minutes = ceil(($finish-$start) / 60); if ($minutes >= variable_get('stormquicktt_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['stormquicktt_ttid'])) { $node = new stdClass(); $node->uid = $user->uid; $node->type = 'stormtimetracking'; $node->title = $name .' ('. variable_get('stormquicktt_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['stormquicktt_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['stormquicktt_note_for_time']) OR empty($node->body)) { $pos = FALSE; } else { $pos = strpos($_SESSION['stormquicktt_note_for_time'], $node->body); } if ($pos === FALSE) { $node->body .= $_SESSION['stormquicktt_note_for_time']; } else { $node->body = $_SESSION['stormquicktt_note_for_time']; } $_SESSION['stormquicktt_note_for_time'] = $node->body; node_save($node); variable_set('stormtimetracking_auto_duration', $old_stormtimetracking_auto_duration); if ($stop) { unset($_SESSION['stormquicktt_ttid']); } else { $_SESSION['stormquicktt_ttid'] = $node->nid; return ''; } $destination = ($_GET['q'] == 'stormdashboard/interact') ? 'stormdashboard' : $_GET['q']; $link = l(t('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['stormquicktt_pause_start'] = 0; $_SESSION['stormquicktt_pause_collect'] = 0; return '
'. $msg .'
'; } function stormquicktt_note_for_time($text) { $_SESSION['stormquicktt_note_for_time'] .= "

". $text ."

\n"; } function stormquicktt_tracking_active_nid() { if (!stormquicktt_tracking_active()) { return 0; } $oid = $_SESSION['stormquicktt_oid']; $pid = $_SESSION['stormquicktt_pid']; $tid = $_SESSION['stormquicktt_tid']; $kid = $_SESSION['stormquicktt_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 stormquicktt_tracking_active_type() { if (!stormquicktt_tracking_active()) { return NULL; } $oid = $_SESSION['stormquicktt_oid']; $pid = $_SESSION['stormquicktt_pid']; $tid = $_SESSION['stormquicktt_tid']; $kid = $_SESSION['stormquicktt_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 stormquicktt_tracking_active() { return !empty($_SESSION['stormquicktt_oid']); } function stormquicktt_tracking_start() { return stormquicktt_tracking_active() ? $_SESSION['stormquicktt_start'] : 0; } function stormquicktt_tracking_info() { $output = ''; if (stormquicktt_tracking_active()) { $oid = $_SESSION['stormquicktt_oid']; $pid = $_SESSION['stormquicktt_pid']; $tid = $_SESSION['stormquicktt_tid']; $kid = $_SESSION['stormquicktt_kid']; $start = $_SESSION['stormquicktt_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' => stormquicktt_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' => stormquicktt_noteform())) .'
'; } else { $output .= '
'. t('Currently not tracking any time.') .'
'; } $output .= ''; return $output; } function stormquicktt_start_link() { if (!empty($_SESSION['stormquicktt_kid'])) { $nid = $_SESSION['stormquicktt_kid']; } elseif (!empty($_SESSION['stormquicktt_tid'])) { $nid = $_SESSION['stormquicktt_tid']; } elseif (!empty($_SESSION['stormquicktt_pid'])) { $nid = $_SESSION['stormquicktt_pid']; } elseif (!empty($_SESSION['stormquicktt_oid'])) { $nid = $_SESSION['stormquicktt_oid']; } if (!empty($nid)) { if (!empty($_SESSION['stormquicktt_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'); $path = variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons'); */ $path = url(variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons'), array('absolute' => TRUE, 'language' => '')); $title_pause = t('Pause'); $title_resume = t('Resume'); $text = '
'. format_date($_SESSION['stormquicktt_start']) .'
'; $text .= '
'. stormquicktt_elapsed_time() .''. $text_paused .'
'; $text .= ''. $title_pause .''; $text .= ''. $title_resume .''; $text .= stormquicktt_timetracking_trigger($nid, FALSE); return $text; } return format_date(time()); } function stormquicktt_noteform() { return '
'; } /** * Returns the sanitized clickable icon to start/stop time tracking */ function stormquicktt_timetracking_trigger($nid = 0, $info = TRUE) { if (!user_access('Storm timetracking: add')) { return ''; } stormquicktt_add_resources(); $active = FALSE; if (!empty($nid) && stormquicktt_tracking_active() && stormquicktt_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, 'language' => '')); $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, 'language' => '')); $class = "timetracking-active"; $info_txt = ' '.t('Click to stop timetracking'); } if (!$info) { $info_txt = ''; } return ''. ''. $title .''. '' . $info_txt . ''; } function stormquicktt_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']['stormquicktt_timetracking_trigger'] = array( '#value' => stormquicktt_timetracking_trigger($node->nid), '#weight' => 12, ); } }