dolibarr  19.0.0-dev
ganttview.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
26 require "../main.inc.php";
27 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35 
36 $id = GETPOST('id', 'intcomma');
37 $ref = GETPOST('ref', 'alpha');
38 
39 $mode = GETPOST('mode', 'alpha');
40 $mine = ($mode == 'mine' ? 1 : 0);
41 //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
42 
43 $object = new Project($db);
44 
45 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
46 if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($object, 'fetchComments') && empty($object->comments)) {
47  $object->fetchComments();
48 }
49 
50 // Security check
51 $socid = 0;
52 //if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement.
53 $result = restrictedArea($user, 'projet', $id, 'projet&project');
54 
55 // Load translation files required by the page
56 $langs->loadlangs(array('users', 'projects'));
57 
58 
59 /*
60  * Actions
61  */
62 
63 // None
64 
65 
66 /*
67  * View
68  */
69 
70 $form = new Form($db);
71 $formother = new FormOther($db);
72 $userstatic = new User($db);
73 $companystatic = new Societe($db);
74 $contactstatic = new Contact($db);
75 $task = new Task($db);
76 
77 $arrayofcss = array('/includes/jsgantt/jsgantt.css');
78 
79 if (!empty($conf->use_javascript_ajax)) {
80  $arrayofjs = array(
81  '/includes/jsgantt/jsgantt.js',
82  '/projet/jsgantt_language.js.php?lang='.$langs->defaultlang
83  );
84 }
85 
86 //$title=$langs->trans("Gantt").($object->ref?' - '.$object->ref.' '.$object->name:'');
87 $title = $langs->trans("Gantt");
88 if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) {
89  $title = ($object->ref ? $object->ref.' '.$object->name.' - ' : '').$langs->trans("Gantt");
90 }
91 $help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
92 
93 llxHeader("", $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss);
94 
95 if (($id > 0 && is_numeric($id)) || !empty($ref)) {
96  // To verify role of users
97  //$userAccess = $object->restrictedProjectArea($user,'read');
98  $userWrite = $object->restrictedProjectArea($user, 'write');
99  //$userDelete = $object->restrictedProjectArea($user,'delete');
100  //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
101 
102  $tab = 'tasks';
103 
104  $head = project_prepare_head($object);
105  print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
106 
107  $param = ($mode == 'mine' ? '&mode=mine' : '');
108 
109 
110 
111  // Project card
112 
113  $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
114 
115  $morehtmlref = '<div class="refidno">';
116  // Title
117  $morehtmlref .= $object->title;
118  // Thirdparty
119  if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
120  $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
121  }
122  $morehtmlref .= '</div>';
123 
124  // Define a complementary filter for search of next/prev ref.
125  if (empty($user->rights->projet->all->lire)) {
126  $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
127  $object->next_prev_filter = " rowid IN (".$db->sanitize(count($objectsListId) ?join(',', array_keys($objectsListId)) : '0').")";
128  }
129 
130  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
131 
132 
133  print '<div class="fichecenter">';
134  print '<div class="fichehalfleft">';
135  print '<div class="underbanner clearboth"></div>';
136 
137  print '<table class="border tableforfield centpercent">';
138 
139  // Usage
140  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
141  print '<tr><td class="tdtop">';
142  print $langs->trans("Usage");
143  print '</td>';
144  print '<td>';
145  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
146  print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
147  $htmltext = $langs->trans("ProjectFollowOpportunity");
148  print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
149  print '<br>';
150  }
151  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
152  print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
153  $htmltext = $langs->trans("ProjectFollowTasks");
154  print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
155  print '<br>';
156  }
157  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
158  print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
159  $htmltext = $langs->trans("ProjectBillTimeDescription");
160  print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
161  print '<br>';
162  }
163  if (isModEnabled('eventorganization')) {
164  print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')).'"> ';
165  $htmltext = $langs->trans("EventOrganizationDescriptionLong");
166  print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
167  }
168  print '</td></tr>';
169  }
170 
171  // Visibility
172  print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
173  if ($object->public) {
174  print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
175  print $langs->trans('SharedProject');
176  } else {
177  print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
178  print $langs->trans('PrivateProject');
179  }
180  print '</td></tr>';
181 
182  // Budget
183  print '<tr><td>'.$langs->trans("Budget").'</td><td>';
184  if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
185  print price($object->budget_amount, '', $langs, 1, 0, 0, $conf->currency);
186  }
187  print '</td></tr>';
188 
189  // Date start - end project
190  print '<tr><td>'.$langs->trans("Dates").'</td><td>';
191  $start = dol_print_date($object->date_start, 'day');
192  print ($start ? $start : '?');
193  $end = dol_print_date($object->date_end, 'day');
194  print ' - ';
195  print ($end ? $end : '?');
196  if ($object->hasDelay()) {
197  print img_warning("Late");
198  }
199  print '</td></tr>';
200 
201  // Other attributes
202  $cols = 2;
203  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
204 
205  print '</table>';
206 
207  print '</div>';
208  print '<div class="fichehalfright">';
209  print '<div class="underbanner clearboth"></div>';
210 
211  print '<table class="border tableforfield centpercent">';
212 
213  // Description
214  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
215  print nl2br($object->description);
216  print '</td></tr>';
217 
218  // Categories
219  if (isModEnabled('categorie')) {
220  print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
221  print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
222  print "</td></tr>";
223  }
224 
225  print '</table>';
226 
227  print '</div>';
228  print '</div>';
229 
230  print '<div class="clearboth"></div>';
231 
232  print dol_get_fiche_end();
233 
234  print '<br>';
235 }
236 
237 // Link to create task
238 $linktocreatetaskParam = array();
239 $linktocreatetaskUserRight = false;
240 if ($user->rights->projet->all->creer || $user->rights->projet->creer) {
241  if ($object->public || $userWrite > 0) {
242  $linktocreatetaskUserRight = true;
243  } else {
244  $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
245  }
246 }
247 
248 $linktocreatetask = dolGetButtonTitle($langs->trans('AddTask'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id.'&action=create'.$param.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$object->id), '', $linktocreatetaskUserRight, $linktocreatetaskParam);
249 
250 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss'=>'reposition'));
251 $linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss'=>'reposition marginleftonly btnTitleSelected'));
252 
253 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
254 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask');
255 
256 
257 // Get list of tasks in tasksarray and taskarrayfiltered
258 // We need all tasks (even not limited to a user because a task to user
259 // can have a parent that is not affected to him).
260 $tasksarray = $task->getTasksArray(0, 0, ($object->id ? $object->id : $id), $socid, 0);
261 // We load also tasks limited to a particular user
262 //$tasksrole=($_REQUEST["mode"]=='mine' ? $task->getUserRolesForProjectsOrTasks(null, $user, $object->id, 0) : '');
263 //var_dump($tasksarray);
264 //var_dump($tasksrole);
265 
266 
267 if (count($tasksarray) > 0) {
268  // Show Gant diagram from $taskarray using JSGantt
269 
270  $dateformat = $langs->trans("FormatDateShortJQuery"); // Used by include ganttchart.inc.php later
271  $datehourformat = $langs->trans("FormatDateShortJQuery").' '.$langs->trans("FormatHourShortJQuery"); // Used by include ganttchart.inc.php later
272  $array_contacts = array();
273  $tasks = array();
274  $task_dependencies = array();
275  $taskcursor = 0;
276  foreach ($tasksarray as $key => $val) { // Task array are sorted by "project, position, date"
277  $task->fetch($val->id, '');
278 
279  $idparent = ($val->fk_parent ? $val->fk_parent : '-'.$val->fk_project); // If start with -, id is a project id
280 
281  $tasks[$taskcursor]['task_id'] = $val->id;
282  $tasks[$taskcursor]['task_alternate_id'] = ($taskcursor + 1); // An id that has same order than position (required by ganttchart)
283  $tasks[$taskcursor]['task_project_id'] = $val->fk_project;
284  $tasks[$taskcursor]['task_parent'] = $idparent;
285 
286  $tasks[$taskcursor]['task_is_group'] = 0;
287  $tasks[$taskcursor]['task_css'] = 'gtaskblue';
288  $tasks[$taskcursor]['task_position'] = $val->rang;
289  $tasks[$taskcursor]['task_planned_workload'] = $val->planned_workload;
290 
291  if ($val->fk_parent != 0 && $task->hasChildren() > 0) {
292  $tasks[$taskcursor]['task_is_group'] = 1;
293  $tasks[$taskcursor]['task_css'] = 'ggroupblack';
294  //$tasks[$taskcursor]['task_css'] = 'gtaskblue';
295  } elseif ($task->hasChildren() > 0) {
296  $tasks[$taskcursor]['task_is_group'] = 1;
297  //$tasks[$taskcursor]['task_is_group'] = 0;
298  $tasks[$taskcursor]['task_css'] = 'ggroupblack';
299  //$tasks[$taskcursor]['task_css'] = 'gtaskblue';
300  }
301  $tasks[$taskcursor]['task_milestone'] = '0';
302  $tasks[$taskcursor]['task_percent_complete'] = $val->progress;
303  //$tasks[$taskcursor]['task_name']=$task->getNomUrl(1);
304  //print dol_print_date($val->date_start).dol_print_date($val->date_end).'<br>'."\n";
305  $tasks[$taskcursor]['task_name'] = $val->ref.' - '.$val->label;
306  $tasks[$taskcursor]['task_start_date'] = $val->date_start;
307  $tasks[$taskcursor]['task_end_date'] = $val->date_end;
308  $tasks[$taskcursor]['task_color'] = 'b4d1ea';
309 
310  $idofusers = $task->getListContactId('internal');
311  $idofcontacts = $task->getListContactId('external');
312  $s = '';
313  if (count($idofusers) > 0) {
314  $s .= $langs->trans("Internals").': ';
315  $i = 0;
316  foreach ($idofusers as $valid) {
317  $userstatic->fetch($valid);
318  if ($i) {
319  $s .= ', ';
320  }
321  $s .= $userstatic->login;
322  $i++;
323  }
324  }
325  //if (count($idofusers)>0 && (count($idofcontacts)>0)) $s.=' - ';
326  if (count($idofcontacts) > 0) {
327  if ($s) {
328  $s .= ' - ';
329  }
330  $s .= $langs->trans("Externals").': ';
331  $i = 0;
332  $contactidfound = array();
333  foreach ($idofcontacts as $valid) {
334  if (empty($contactidfound[$valid])) {
335  $res = $contactstatic->fetch($valid);
336  if ($res > 0) {
337  if ($i) {
338  $s .= ', ';
339  }
340  $s .= $contactstatic->getFullName($langs);
341  $contactidfound[$valid] = 1;
342  $i++;
343  }
344  }
345  }
346  }
347 
348  /* For JSGanttImproved */
349  //if ($s) $tasks[$taskcursor]['task_resources']=implode(',',$idofusers);
350  $tasks[$taskcursor]['task_resources'] = $s;
351  if ($s) {
352  $tasks[$taskcursor]['task_resources'] = '<a href="'.DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$val->id.'&withproject=1" title="'.dol_escape_htmltag($s).'">'.$langs->trans("List").'</a>';
353  }
354  //print "xxx".$val->id.$tasks[$taskcursor]['task_resources'];
355  $tasks[$taskcursor]['note'] = $task->note_public;
356  $taskcursor++;
357  }
358 
359  // Search parent to set task_parent_alternate_id (requird by ganttchart)
360  foreach ($tasks as $tmpkey => $tmptask) {
361  foreach ($tasks as $tmptask2) {
362  if ($tmptask2['task_id'] == $tmptask['task_parent']) {
363  $tasks[$tmpkey]['task_parent_alternate_id'] = $tmptask2['task_alternate_id'];
364  break;
365  }
366  }
367  if (empty($tasks[$tmpkey]['task_parent_alternate_id'])) {
368  $tasks[$tmpkey]['task_parent_alternate_id'] = $tasks[$tmpkey]['task_parent'];
369  }
370  }
371 
372  print "\n";
373 
374  if (!empty($conf->use_javascript_ajax)) {
375  //var_dump($_SESSION);
376 
377  // How the date for data are formated (format used bu jsgantt)
378  $dateformatinput = 'yyyy-mm-dd';
379  // How the date for data are formated (format used by dol_print_date)
380  $dateformatinput2 = 'standard';
381  //var_dump($dateformatinput);
382  //var_dump($dateformatinput2);
383 
384  $moreforfilter = '<div class="liste_titre liste_titre_bydiv centpercent">';
385 
386  $moreforfilter .= '<div class="divsearchfield">';
387  //$moreforfilter .= $langs->trans("TasksAssignedTo").': ';
388  //$moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', 1);
389  $moreforfilter .= '&nbsp;';
390  $moreforfilter .= '</div>';
391 
392  $moreforfilter .= '</div>';
393 
394  print $moreforfilter;
395 
396  print '<div class="div-table-responsive">';
397 
398  print '<div id="tabs" class="gantt" style="width: 80vw;">'."\n";
399  include_once DOL_DOCUMENT_ROOT.'/projet/ganttchart.inc.php';
400  print '</div>'."\n";
401 
402  print '</div>';
403  } else {
404  $langs->load("admin");
405  print $langs->trans("AvailableOnlyIfJavascriptAndAjaxNotDisabled");
406  }
407 } else {
408  print '<div class="opacitymedium">'.$langs->trans("NoTasks").'</div>';
409 }
410 
411 // End of page
412 llxFooter();
413 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage contact/addresses.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:40
Class to manage Dolibarr users.
Definition: user.class.php:48
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
isModEnabled($module)
Is Dolibarr module enabled.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
Definition: project.lib.php:39
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.