* @version $Id$ * @access public * @license http://opensource.org/licenses/gpl-3.0.html */ $noplugin = true; // flag for ../config/define.php file include_once('../config/define.php'); include_once('../languages/' . U_L . '/lang_project.' . CHARSET . '.php'); include_once('../languages/' . U_L . '/lang_common.' . CHARSET . '.php'); include_once("../level/".SQL.".inc.php"); include_once("../project/".SQL.".inc.php"); include_once("../admin/".SQL.".inc.php"); include_once(override('../project/display.php')); securityCheck(); isset($_REQUEST['id']) ? $id = $_REQUEST['id'] : die("no way"); ////////// Check Droits utilisateur //////////// if (!$l21auth->isAuthenticated() || (!$l21auth->hasRight('project') && ! $l21auth->isSuperAdmin())) ReloadIndex('admin'); ////////// ///////////////////////////////////// function get_gantt_item_properties($startDate, $endDate, $config) { $properties = []; if(date_compare($endDate, $config['year-end'].'-12-31', '>')) $endDate = $config['year-end'].'-12-31'; // if endDate is out of bound, we take $config['year-end'] as reference if(date_compare($startDate, $config['year-start'].'-01-01', '<')) $startDate = $config['year-start'].'-01-01';// if startDate is out of bound, we take $config['year-start'] as reference // we calculate numbers of days between start and end dates $datediff = strtotime($endDate) - strtotime($startDate); $properties['numberOfDays'] = round($datediff / (60 * 60 * 24)); // we also calculate numbers of days between start date and $config['year-start'].'-01-01' to define the offset $dateOffset = strtotime($startDate) - strtotime($config['year-start'].'-01-01'); $dateOffsetDays = round($dateOffset / (60 * 60 * 24)); $properties['numberOfDays'] = round($datediff / (60 * 60 * 24)); $properties['width'] = round(($config['year-width'] * $config['yearsNumber']) * $properties['numberOfDays'] / (365 * $config['yearsNumber'])); $properties['offset'] = round($dateOffsetDays * ($config['year-width'] * $config['yearsNumber']) / (365 * $config['yearsNumber']) ); return $properties; } function get_subdivisions($width, $nb) { $s = ''; for($i = 0; $i < $nb; $i++) { // we substract $nb to width beacase of border width $s .= '
'; } return $s; } function generate_recursive_content($data, $statut, $config, $output) { // loop through all items in this level foreach ($data as $key => &$item) { // echo "$key

"; // where only interested in numeric items // as those are the actual children if (! is_numeric($key)) { // otherwise continue continue; } // 'level_parent' attribute is not set when there is no children level if (isset($item['level_parent'])) { if(!empty($item['level_code'])) $display = $item['level_code']; else $display = cutText($item['level_name'], 40); $output['labels'] .= '
'.$display .'
'; $output['rows'] .= '
'; } $projects = $GLOBALS['sql_object']->DBSelect(SQL_getProjectsList(0, 999, $statut, 'LEVEL', $item['level_id'])); if (is_array($projects)) { for ($i = 0; $i < count($projects); $i ++) { $link_detail = '../admin/index.php?rub=project&todo=det&id='.$projects[$i]['project_id']; $project_name = formatText(mb_ucfirst($projects[$i]['complete_project_name']), '2HTML'); $class=""; //if(!isNullDate($projects[$i]['project_begin_date_display'])) $startDate = $projects[$i]['project_begin_date_display']; $startDate = $projects[$i]['project_begin_date_display']; if(!isNullDate($projects[$i]['project_estimated_date_display'])) { $endDate = $projects[$i]['project_estimated_date_display']; $class= 'in-progress'; } else { $endDate = empty_nc(''); $class= 'in-progress'; } if(!isNullDate($projects[$i]['project_end_date_display'])) { $endDate = $projects[$i]['project_end_date_display']; $class= 'done'; } // if dates of action are out of range, we do not display anything //// format : '0001-01-01' $flag = true; if(date_compare($endDate, $config['year-start'].'-01-01', '<')) $flag = false; // echo $startDate.'xxx'.$projects[$i]['project_id'].'
'; if(date_compare($startDate, $config['year-end'].'-12-31', '>')) $flag = false; // if there is no starting date, we do not display anything if(isNullDate($projects[$i]['project_begin_date_display']) || ( isNullDate($projects[$i]['project_estimated_date_display']) && isNullDate($projects[$i]['project_end_date_display']) )) { $output['nocal'] .= '
  • '.$project_name .' ('.$item['level_name'].')
  • '; $flag = false; } // we add css style to show that action is longer than current calendar if(date_compare($endDate, $config['year-end'].'-12-31', '>')) $class .= ' ends-after'; if(date_compare($startDate, $config['year-start'].'-01-01', '<')) $class .= ' starts-before'; if ($projects[$i]['project_parent_id'] != 0) $class .= ' sub-project'; if($flag) { // first we set labels $output['labels'] .= '
    '.cutText($project_name, 50) .'
    '; ($config['dates-always-visible'] == 1) ? $alwaysvisible = ' style="display:block"' : $alwaysvisible = ''; $csstip = $project_name. ' [' . _t('project', 'progression') . ' : ' .$projects[$i]['project_completed'].']'; if($projects[$i]['project_completed'] == 100) $csstip = '✓ ' . $csstip; // then we create gantt rows $props = get_gantt_item_properties($startDate, $endDate, $config); $output['rows'] .= '
    '.$startDate.' '.$endDate.'
    '; // and finally, we create a legend $output['legend'] .= '
    '.($i+1) .' '.$project_name.'
    '.PHP_EOL; } } // boucle projet } // test si projet // call this funcion recursively // with the next level ($item) // it will figure out again whether that level has numeric children as well // returns a new complete set, if applicable, otherwise an empty string if (isset($item['children'])) $output = generate_recursive_content($item['children'], $statut, $config, $output); } // return strings into array return $output; } ///////////////////////////////////// // we prepare environnement ///////////////////////////////////// // default values $config = []; $config['year-width'] = 365; $config['year-start'] = ''; $config['year-end'] = ''; $config['subdivision'] = 12; $config['dates-always-visible'] = 0; $config['show-no-dates'] = 1; // we get timeline information given in PROJECT_TIMELINE constant $timeline = get_timeline_info(); // we override default values if(isset($timeline['year-width'])) $config['year-width'] = $timeline['year-width']; if(isset($timeline['subdivision'])) $config['subdivision'] = $timeline['subdivision']; if(isset($timeline['dates-always-visible'])) $config['dates-always-visible'] = $timeline['dates-always-visible']; if(isset($timeline['show-no-dates'])) $config['show-no-dates'] = $timeline['show-no-dates']; // years is mandatory !!! list($config['year-start'], $config['year-end']) = explode('-', $timeline['years']); // if order is not correct, we invert dates if($config['year-start'] > $config['year-end']) { $tmp = $config['year-end']; $config['year-end'] = $config['year-start']; $config['year-start'] = $tmp; } $config['yearsNumber'] = ($config['year-end'] - $config['year-start']) + 1; ///////////////////////////////////// // environnement is set and now available through 'config' array // we start to create content ///////////////////////////////////// $current = $GLOBALS['sql_object']->DBSelect(SQL_getoneLevel($id)); $data = getLevelChildren($GLOBALS['sql_object']->DBSelect(SQL_getLevelsList()), $id); $sublevels = array_extract($data, 'level_id', true, 'children'); // if there is no sub-menu, we are working on last levels // we emulate a level by passing choosen level but 'level_parent' is not set if (count($sublevels) == 0) { $sublevels = array($id); $data = $current; } $output = []; $output['labels'] = ''; $output['rows'] = ''; $output['legend'] = ''; $output['nocal'] = ''; $gantt = generate_recursive_content($data, 'all', $config, $output); // A - we generate html code for Years and sub-divisions $years = ''; $cnt = 0; for($i = $config['year-start']; $i <= $config['year-end']; $i++) { $subs = get_subdivisions($config['year-width'], $config['subdivision']); $years .= '
    ' . $i . '
    '.$subs.'
    ' . PHP_EOL; $cnt++; } // B - we generate labels and gantt row based on fetched actions // model adapted from : https://codepen.io/carlo-peluso/pen/XWWJwYE $content = '
    ' . $gantt['labels']. '
    '. $years . '
    ' . $gantt['rows']. '
    '; $js = ''; $content .= $js; if(!empty($gantt['nocal']) && $config['show-no-dates'] == 1) $content .= sprintf('

    '._t('project', 'missing-dates').' :

    ', $gantt['nocal']); $content = sprintf('
    %s
    ', $content); // generateHTMLPage($mainContent, 'admin', $cssfiles = array(), $jsfiles = array(), $title = SITE_NAME) echo generateHTMLPage($content, 'admin', array('css/admin_gantt.css'), array('lib/js/html2canvas/dist/html2canvas.min-v1.4.1.js'), SITE_NAME) ?>