This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".

The branch, master has been updated
       via  5774e19d32c999405f3b55ca416b18796c7495e2 (commit)
      from  99284323dcf85a14a2ed1fce2406e85d03192373 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=5774e19d32c999405f3b55ca416b18796c7495e2

commit 5774e19d32c999405f3b55ca416b18796c7495e2
Author: Franck Villaume <[email protected]>
Date:   Sun Nov 20 17:12:06 2016 +0100

    new artifact display option: set use_tracker_widget_display to enable it

diff --git a/src/common/tracker/Artifact.class.php 
b/src/common/tracker/Artifact.class.php
index 7d4fc09..2d9bd51 100644
--- a/src/common/tracker/Artifact.class.php
+++ b/src/common/tracker/Artifact.class.php
@@ -58,6 +58,8 @@ require_once $gfcommon.'include/MonitorElement.class.php';
 // user response
 define('ARTIFACT_MAIL_MARKER', '#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+#+');
 
+$ARTIFACT_OBJ = array();
+
 /**
  * Factory method which creates an Artifact from an artifact ID
  *
@@ -672,6 +674,12 @@ class Artifact extends FFObject {
                                        array ($this->getID())) ;
        }
 
+       function hasMessages() {
+               $res = db_query_params('SELECT count(id) FROM artifact_message 
WHERE artifact_id=$1', array($this->getID()));
+               $row = db_fetch_array($res);
+               return $row[0];
+       }
+
        /**
         * getMessages - get the list of messages attached to this artifact.
         *
diff --git a/src/common/tracker/ArtifactExtraField.class.php 
b/src/common/tracker/ArtifactExtraField.class.php
index fe0d54c..c788cb6 100644
--- a/src/common/tracker/ArtifactExtraField.class.php
+++ b/src/common/tracker/ArtifactExtraField.class.php
@@ -721,7 +721,7 @@ class ArtifactExtraField extends FFError {
                                }
                        } elseif (in_array($type, 
unserialize(ARTIFACT_EXTRAFIELDTYPEGROUP_MULTICHOICE))) {
                                while ($row = db_fetch_array($res)) {
-                                       if (!is_null($default) && 
in_array($row['element_id'],$default)) {
+                                       if (is_array($default) && 
in_array($row['element_id'], $default)) {
                                                $row['is_default']=1;
                                        }
                                        $return[] = $row;
diff --git a/src/common/tracker/ArtifactFactory.class.php 
b/src/common/tracker/ArtifactFactory.class.php
index cbd1c7d..7b0f2ad 100644
--- a/src/common/tracker/ArtifactFactory.class.php
+++ b/src/common/tracker/ArtifactFactory.class.php
@@ -141,7 +141,7 @@ class ArtifactFactory extends FFError {
                                                $order_col=$pref_arr[2];
                                                $sort=$pref_arr[3];
                                                $_changed=$pref_arr[4];
-                                               if 
($this->ArtifactType->usesCustomStatuses()) {
+                                               if 
($this->ArtifactType->usesCustomStatuses() && isset($pref_arr[5])) {
                                                        
$_extra_fields=unserialize($pref_arr[5]);
                                                } else {
                                                        $_status=$pref_arr[1];
diff --git a/src/common/tracker/ArtifactType.class.php 
b/src/common/tracker/ArtifactType.class.php
index 6c3b4a6..d5ee5ba 100644
--- a/src/common/tracker/ArtifactType.class.php
+++ b/src/common/tracker/ArtifactType.class.php
@@ -966,12 +966,12 @@ class ArtifactType extends FFError {
                        return 'None';
                }
                if (!isset($this->element_name[$choice_id])) {
-                       $res = db_query_params('SELECT 
element_id,extra_field_id,element_name
+                       $res = db_query_params('SELECT element_id, element_name
                                FROM artifact_extra_field_elements
                                WHERE element_id = ANY ($1)',
                                                
array(db_int_array_to_any_clause(explode(',', $choice_id))));
                        if (db_numrows($res) > 1) {
-                               $arr = util_result_column_to_array($res, 2);
+                               $arr = util_result_column_to_array($res, 1);
                                $this->element_name[$choice_id] = implode(',', 
$arr);
                        } else {
                                $this->element_name[$choice_id] = 
db_result($res, 0, 'element_name');
diff --git a/src/common/tracker/actions/ajax.php 
b/src/common/tracker/actions/ajax.php
index 087f531..5397d9d 100644
--- a/src/common/tracker/actions/ajax.php
+++ b/src/common/tracker/actions/ajax.php
@@ -21,6 +21,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+$sysdebug_enable = false;
+
 $function = getStringFromRequest('function');
 
 switch ($function) {
diff --git a/src/common/tracker/actions/browse.php 
b/src/common/tracker/actions/browse.php
index 0222289..4329971 100644
--- a/src/common/tracker/actions/browse.php
+++ b/src/common/tracker/actions/browse.php
@@ -394,7 +394,7 @@ if (db_numrows($res)>0) {
        echo '
                <script type="text/javascript">//<![CDATA[
                jQuery("#query_id").change(function() {
-                       location.href = 
'.util_make_url('/tracker/?group_id='.$group_id.'&atid='.$ath->getID().'&power_query=1&query_id=').'+jQuery("#query_id").val();
+                       location.href = 
"'.util_make_url('/tracker/?group_id='.$group_id.'&atid='.$ath->getID().'&power_query=1&query_id=').'"+jQuery("#query_id").val();
                });
                //]]></script>';
 } else {
diff --git a/src/common/tracker/actions/detail.php 
b/src/common/tracker/actions/detail.php
index 26e7cbb..21aacdf 100644
--- a/src/common/tracker/actions/detail.php
+++ b/src/common/tracker/actions/detail.php
@@ -123,7 +123,7 @@ echo $HTML->listTableTop(); ?>
 
                <tr><td colspan="2">
                        <br />
-                       <?php $ah->showDetails(); ?>
+                       <?php echo $ah->showDetails(); ?>
                </td></tr>
 <?php echo $HTML->listTableBottom(); ?>
 <?php
@@ -180,7 +180,7 @@ foreach ($pluginsListeners as $pluginsListener) {
                        </td></tr>
                        <?php } ?>
                        <tr><td colspan="2">
-                       <?php $ah->showMessages(); ?>
+                       <?php echo $ah->showMessages(); ?>
                        </td></tr>
        <?php echo $HTML->listTableBottom(); ?>
        </div>
@@ -189,7 +189,7 @@ if ($group->usesPM()) {
 ?>
 <div id="tabber-tasks" class="tabbertab">
        <?php
-               $ath->renderRelatedTasks($group, $ah);
+               echo $ath->renderRelatedTasks($group, $ah);
        ?>
 </div>
 <?php }
@@ -205,14 +205,13 @@ if ($group->usesPM()) {
                        <input type="file" name="input_file3" /><br />
                        <input type="file" name="input_file4" /><br />
                <?php } ?>
-               <?php
-               //
-               // print a list of files attached to this Artifact
-               //
-                       $ath->renderFiles($group_id, $ah);
-               ?>
                </td></tr>
-       <?php echo $HTML->listTableBottom(); ?>
+       <?php echo $HTML->listTableBottom();
+       //
+       // print a list of files attached to this Artifact
+       //
+       echo $ath->renderFiles($group_id, $ah);
+       ?>
        </div>
 <?php
        if ($pluginfound) {
@@ -231,10 +230,10 @@ if ($group->usesPM()) {
        }
 ?>
        <div id="tabber-changes" class="tabbertab">
-               <?php $ah->showHistory(); ?>
+               <?php echo $ah->showHistory(); ?>
        </div>
-       <?php $ah->showRelations(); ?>
-       <?php if (forge_get_config('use_object_associations')) { ?>
+       <?php echo $ah->showRelations();
+       if (forge_get_config('use_object_associations')) { ?>
        <div id="tabber-object-associations" class="tabbertab">
        <?php if (forge_check_perm ('tracker',$ath->getID(),'submit')) {
                        echo 
$ah->showAssociations('/tracker/?rtype=ajax&aid='.$ah->getID().'&group_id='.$ath->Group->getID().'&atid='.$ath->getID().'&func=removeassoc');
diff --git a/src/common/tracker/actions/mod-limited.php 
b/src/common/tracker/actions/mod-limited.php
index 00858e6..b809aef 100644
--- a/src/common/tracker/actions/mod-limited.php
+++ b/src/common/tracker/actions/mod-limited.php
@@ -155,7 +155,7 @@ echo $HTML->listTableTop(); ?>
        </tr>
        <tr><td colspan="2">
                <br />
-               <?php $ah->showDetails(); ?>
+               <?php echo $ah->showDetails(); ?>
        </td></tr>
 <?php echo $HTML->listTableBottom(); ?>
 <div id="tabber">
@@ -203,7 +203,7 @@ foreach ($pluginsListeners as $pluginsListener) {
                        <textarea id="tracker-comment" name="details" rows="7" 
style="width: 100%" title="<?php echo 
util_html_secure(html_get_tooltip_description('comment')) ?>"></textarea>
                        <p>
                        <?php
-       $ah->showMessages();
+       echo $ah->showMessages();
                        ?>
                </td></tr>
        <?php echo $HTML->listTableBottom(); ?>
@@ -213,7 +213,7 @@ if ($group->usesPM()) {
 ?>
 <div id="tabber-tasks" class="tabbertab">
        <?php
-               $ath->renderRelatedTasks($group, $ah);
+               echo $ath->renderRelatedTasks($group, $ah);
        ?>
 </div>
 <?php }
@@ -227,16 +227,13 @@ if ($group->usesPM()) {
                <input type="file" name="input_file2" size="30" /><br />
                <input type="file" name="input_file3" size="30" /><br />
                <input type="file" name="input_file4" size="30" />
-               <p>
-               <h2><?php echo _('Attached Files')._(':'); ?></h2>
-               <?php
-               //
-               // print a list of files attached to this Artifact
-               //
-                       $ath->renderFiles($group_id, $ah);
-               ?>
        </td></tr>
-<?php echo $HTML->listTableBottom(); ?>
+<?php echo $HTML->listTableBottom();
+//
+// print a list of files attached to this Artifact
+//
+echo $ath->renderFiles($group_id, $ah);
+?>
 </div>
 <?php if ($pluginfound) { ?>
 <div id="tabber-commits" class="tabbertab">
@@ -251,10 +248,10 @@ if ($group->usesPM()) {
 </div>
 <?php } ?>
 <div id="tabber-changes" class="tabbertab">
-       <?php $ah->showHistory(); ?>
+       <?php echo $ah->showHistory(); ?>
 </div>
-<?php $ah->showRelations(); ?>
-<?php if (forge_get_config('use_object_associations')) { ?>
+<?php echo $ah->showRelations();
+if (forge_get_config('use_object_associations')) { ?>
 <div id="tabber-object-associations" class="tabbertab">
        <?php if (forge_check_perm ('tracker',$ath->getID(),'submit')) {
                        echo 
$ah->showAssociations('/tracker/?rtype=ajax&aid='.$ah->getID().'&group_id='.$ath->Group->getID().'&atid='.$ath->getID().'&func=removeassoc');
diff --git a/src/common/tracker/actions/mod.php 
b/src/common/tracker/actions/mod.php
index e9638a0..f25cd0e 100644
--- a/src/common/tracker/actions/mod.php
+++ b/src/common/tracker/actions/mod.php
@@ -194,7 +194,7 @@ echo html_build_select_box 
($res,'new_artifact_type_id',$ath->getID(),false);
                <textarea id="tracker-description" required="required" 
name="description" rows="30" style="width: 100%" title="<?php echo 
html_get_tooltip_description('description') ?>"><?php echo $ah->getDetails(); 
?></textarea>
                </div>
                <div id="show" style="display:block;">
-               <?php $ah->showDetails(true); ?>
+               <?php echo $ah->showDetails(true); ?>
                </div>
        </td></tr>
 <?php echo $HTML->listTableBottom(); ?>
@@ -265,9 +265,7 @@ foreach ($pluginsListeners as $pluginsListener) {
                <p>
                <strong><?php echo _('Post Comment')._(': ') ?><?php echo 
notepad_button('document.forms.trackermodform.details') ?></strong><br />
                <textarea id="tracker-comment" name="details" rows="7" 
style="width: 100%" title="<?php echo 
util_html_secure(html_get_tooltip_description('comment')) ?>"></textarea></p>
-               <?php
-$ah->showMessages();
-               ?>
+               <?php echo $ah->showMessages(); ?>
        </td></tr>
 <?php echo $HTML->listTableBottom(); ?>
 </div>
@@ -290,14 +288,13 @@ if ($group->usesPM()) {
         <input type="file" name="input_file2" size="30" /><br />
         <input type="file" name="input_file3" size="30" /><br />
         <input type="file" name="input_file4" size="30" /><br />
-               <?php
-               //
-               // print a list of files attached to this Artifact
-               //
-               $ath->renderFiles($group_id, $ah);
-               ?>
        </td></tr>
-<?php echo $HTML->listTableBottom(); ?>
+<?php echo $HTML->listTableBottom();
+//
+// print a list of files attached to this Artifact
+//
+echo $ath->renderFiles($group_id, $ah);
+?>
 </div>
 <?php if ($pluginfound) { ?>
 <div id="tabber-commits" class="tabbertab">
@@ -312,10 +309,10 @@ if ($group->usesPM()) {
 </div>
 <?php } ?>
 <div id="tabber-changes" class="tabbertab">
-       <?php $ah->showHistory(); ?>
+       <?php echo $ah->showHistory(); ?>
 </div>
-       <?php $ah->showRelations(); ?>
-       <?php if (forge_get_config('use_object_associations')) { ?>
+       <?php echo $ah->showRelations();
+       if (forge_get_config('use_object_associations')) { ?>
        <div id="tabber-object-associations" class="tabbertab">
        <?php if (forge_check_perm ('tracker',$ath->getID(),'submit')) {
                        echo 
$ah->showAssociations('/tracker/?func=removeassoc&aid='.$ah->getID().'&group_id='.$ath->Group->getID().'&atid='.$ath->getID());
diff --git a/src/common/tracker/actions/tracker.php 
b/src/common/tracker/actions/tracker.php
index 97f6f09..ca92273 100644
--- a/src/common/tracker/actions/tracker.php
+++ b/src/common/tracker/actions/tracker.php
@@ -51,7 +51,11 @@ switch (getStringFromRequest('func')) {
                if (!forge_check_perm ('tracker', $ath->getID(), 'submit')) {
                        exit_permission_denied('tracker');
                }
-               include $gfcommon.'tracker/actions/add.php';
+               if (forge_get_config('use_tracker_widget_display')) {
+                       include 
$gfcommon.'tracker/actions/widget_artifact_display.php';
+               } else {
+                       include $gfcommon.'tracker/actions/add.php';
+               }
                break;
        }
        case 'postadd' : {
@@ -93,7 +97,12 @@ switch (getStringFromRequest('func')) {
                if 
(!$ah->create($summary,$details,$assigned_to,$priority,$extra_fields)) {
                        $error_msg = $ah->getErrorMessage();
                        form_release_key(getStringFromRequest('form_key'));
-                       include $gfcommon.'tracker/actions/add.php';
+                       if (forge_get_config('use_tracker_widget_display')) {
+                               $func = 'add';
+                               include 
$gfcommon.'tracker/actions/widget_artifact_display.php';
+                       } else {
+                               include $gfcommon.'tracker/actions/add.php';
+                       }
                } else {
                        $feedback .= sprintf(_('Item %s successfully 
created'),'[#'.$ah->getID().']');
                        $aid = $ah->getID();
@@ -559,12 +568,16 @@ switch (getStringFromRequest('func')) {
                        exit_error($ah->getErrorMessage(),'tracker');
                } else {
                        html_use_tablesorter();
-                       if (forge_check_perm ('tracker', $ath->getID(), 
'manager')) {
-                               include $gfcommon.'tracker/actions/mod.php';
-                       } elseif (forge_check_perm ('tracker', $ath->getID(), 
'tech')) {
-                               include 
$gfcommon.'tracker/actions/mod-limited.php';
+                       if (forge_get_config('use_tracker_widget_display')) {
+                               include 
$gfcommon.'tracker/actions/widget_artifact_display.php';
                        } else {
-                               include $gfcommon.'tracker/actions/detail.php';
+                               if (forge_check_perm ('tracker', $ath->getID(), 
'manager')) {
+                                       include 
$gfcommon.'tracker/actions/mod.php';
+                               } elseif (forge_check_perm ('tracker', 
$ath->getID(), 'tech')) {
+                                       include 
$gfcommon.'tracker/actions/mod-limited.php';
+                               } else {
+                                       include 
$gfcommon.'tracker/actions/detail.php';
+                               }
                        }
                }
                break;
diff --git a/src/common/tracker/actions/widget_artifact_display.php 
b/src/common/tracker/actions/widget_artifact_display.php
new file mode 100644
index 0000000..d85e72f
--- /dev/null
+++ b/src/common/tracker/actions/widget_artifact_display.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Tracker Widget Artifact Display page
+ *
+ * Copyright 2016 Franck Villaume - TrivialDev
+ * http://fusionforge.org/
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+require_once $gfcommon.'widget/WidgetLayoutManager.class.php';
+
+global $ath;
+global $ah;
+global $group_id;
+global $group;
+global $aid;
+global $atid;
+global $HTML;
+
+if (!isset($func)) {
+       $func = getStringFromRequest('func');
+}
+
+$sql = "SELECT l.*
+               FROM layouts AS l INNER JOIN owner_layouts AS o ON(l.id = 
o.layout_id)
+               WHERE o.owner_type = $1
+               AND o.owner_id = $2
+               AND o.is_default = 1
+               ";
+$res = db_query_params($sql,array('t', $atid));
+if($res && db_numrows($res)<1) {
+       $lm = new WidgetLayoutManager();
+       $lm->createDefaultLayoutForTracker($atid);
+       $res = db_query_params($sql,array('t', $atid));
+}
+$id = db_result($res, 0 , 'id');
+
+html_use_jqueryui();
+html_use_jquerydatetimepicker();
+if ($func == 'add') {
+       $ath->header(array('title' => _('Submit New'), 'modal' => 1));
+} elseif ($func == 'detail') {
+       $ath->header(array('title'=> $ah->getStringID().' '. $ah->getSummary(), 
'atid'=>$ath->getID()));
+}
+
+if (forge_check_perm('tracker_admin', $atid)) {
+       $ap = html_ap();
+       echo html_ao('ul', array('class' => 'widget_toolbar'));
+       $url = '/widgets/widgets.php?owner=t'.$atid.'&layout_id='.$id;
+       $labels = array(_('Add widgets'), _('Customize Layout'));
+       $urls = array($url, $url.'&update=layout');
+       for ($i = 0; $i < count($urls); $i++) {
+               echo html_e('li', array(), util_make_link($urls[$i], 
$labels[$i]));
+       }
+       echo html_ac($ap);
+}
+// plugin_hook('message');
+echo $HTML->openForm(array('name' => 'trackerform', 'action' => 
'/tracker/?group_id='.$group_id.'&atid='.$ath->getID(), 'enctype' => 
'multipart/form-data', 'method' => 'post'));
+echo html_e('input', array('type' => 'hidden', 'name' => 'form_key', 'value' 
=> form_generate_key()));
+if ($func == 'add') {
+       echo html_e('input', array('type' => 'hidden', 'name' => 'func', 
'value' => 'postadd'));
+} elseif ($func == 'detail') {
+       echo html_e('input', array('type' => 'hidden', 'name' => 'func', 
'value' => 'postmod'));
+       echo html_e('input', array('type' => 'hidden', 'name' => 'artifact_id', 
'value' => $ah->getID()));
+}
+$lm = new WidgetLayoutManager();
+$lm->displayLayout($atid, WidgetLayoutManager::OWNER_TYPE_TRACKER);
+echo $HTML->closeForm();
+$ath->footer();
diff --git a/src/common/tracker/include/ArtifactHtml.class.php 
b/src/common/tracker/include/ArtifactHtml.class.php
index 63dac15..3a93a7f 100644
--- a/src/common/tracker/include/ArtifactHtml.class.php
+++ b/src/common/tracker/include/ArtifactHtml.class.php
@@ -37,6 +37,7 @@ class ArtifactHtml extends Artifact {
         */
        function showDetails($editable = false) {
                global $HTML;
+               $return = '';
                $result = $this->getDetails();
                $result_html = util_gen_cross_ref($result, 
$this->ArtifactType->Group->getID());
                //$result = util_line_wrap( $result, 120,"\n");
@@ -44,29 +45,31 @@ class ArtifactHtml extends Artifact {
 
                $title_arr = array();
                if ($editable === true) {
-                       $title_arr[] = '<div style="width:100%;">' .
-                               '<div style="float:left">' . _('Detailed 
description')._(':') . '</div>' .
-                               '<div>' . html_image('ic/forum_edit.gif', 37, 
15, array('title'=>_('Edit this message'), 'alt'=>_('Edit this message'), 
'class' => 'mini_buttons tip-ne', 'onclick'=>"switch2edit(this, 
'showdescription', 'editdescription')")) . '</div>' .
+                       $title_arr[] = '<div style="width:100%; line-height: 
20px;">' .
+                               '<div style="float:left;">' . _('Detailed 
description')._(':') . '</div>' .
+                               '<div>' . $HTML->getEditFilePic(_('Edit this 
message'), _('Edit this message'), array('class' => 'mini_buttons tip-ne', 
'onclick'=>"switch2edit(this, 'showdescription', 'editdescription')")) . 
'</div>' .
                                '</div>';
                } else {
                        $title_arr[] = _('Detailed description');
                }
-               echo $HTML->listTableTop($title_arr);
-               echo $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle(0, true), 'id' => 'editdescription', 'style' => 
'display:none'), array(array(html_e('textarea', array('id' => 
'tracker-description', 'required' => 'required', 'name' => 'description', 
'rows' => 20, 'cols' => 79, 'title' => 
util_html_secure(html_get_tooltip_description('description'))), $result))));
-               echo $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle(0, true), 'id' => 'showdescription'), 
array(array($result_html)));
-               echo $HTML->listTableBottom();
+               $return .= $HTML->listTableTop($title_arr);
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle(0, true), 'id' => 'editdescription', 'style' => 
'display:none'), array(array(html_e('textarea', array('id' => 
'tracker-description', 'required' => 'required', 'name' => 'description', 
'rows' => 20, 'style' => 'box-sizing: box-border; width: 99%;', 'title' => 
util_html_secure(html_get_tooltip_description('description'))), $result), 
'style' => 'display: block; box-sizing:border-box;')));
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle(0, true), 'id' => 'showdescription'), 
array(array($result_html)));
+               $return .= $HTML->listTableBottom();
+               return $return;
        }
 
        function showMessages() {
                global $HTML;
+               $return = '';
                if (session_loggedin()) {
                        $u = session_get_user();
                        $order = $u->getPreference('tracker_messages_order');
                }
                if (!isset($order) || !$order) $order = 'up';
 
-               $result= $this->getMessages($order);
-               $rows=db_numrows($result);
+               $result = $this->getMessages($order);
+               $rows = db_numrows($result);
 
                if ($rows > 0) {
                        $title_arr=array();
@@ -79,117 +82,121 @@ class ArtifactHtml extends Artifact {
                                $img_order = 'up';
                                $char_order = '↑';
                        }
-                       ?>
+                       $return .= '
 <script type="text/javascript">/* <![CDATA[ */
 function show_edit_button(id) {
     var element = document.getElementById(id);
-       if (element) element.style.display = 'block';
+       if (element) element.style.display = "block";
 }
 function hide_edit_button(id) {
     var element = document.getElementById(id);
-       if (element) element.style.display = 'none';
+       if (element) element.style.display = "none";
 }
-/* ]]> */</script>
-                       <?php
-                       echo '<img style="display: none;" id="img_order" src="" 
alt="" />';
-                       echo '<table class="listing full" id="messages_list">
+/* ]]> */</script>';
+                       $return .= '<img style="display: none;" id="img_order" 
src="" alt="" />';
+                       $return .= '<table class="listing full" 
id="messages_list">
 <thead>
 <tr>
 <th>
-<a name="sort" href="#sort" class="sortheader" onclick="thead = 
true;ts_resortTable(this, 0);submitOrder();return false;">Message<span 
id="order_span" sortdir="'.$order.'" class="sortarrow">&nbsp;&nbsp;<img 
src="/images/sort_'.$img_order.'.gif" alt="'.$char_order.'" /></span></a></th>
+<a name="sort" href="#sort" class="sortheader" onclick="thead = 
true;ts_resortTable(this, 0);submitOrder();return false;">'._('Message').'<span 
id="order_span" sortdir="'.$order.'" class="sortarrow">&nbsp;&nbsp;<img 
src="/images/sort_'.$img_order.'.gif" alt="'.$char_order.'" /></span></a></th>
 </tr>
 </thead>
 <tbody>';
 
                        for ($i=0; $i < $rows; $i++) {
-                               echo '<tr 
onmouseover="show_edit_button(\'edit_bt_'.$i.'\')" 
onmouseout="hide_edit_button(\'edit_bt_'.$i.'\')" '. 
$HTML->boxGetAltRowStyle($i) .'><td>';
+                               $return .= '<tr 
onmouseover="show_edit_button(\'edit_bt_'.$i.'\')" 
onmouseout="hide_edit_button(\'edit_bt_'.$i.'\')" ><td>';
 
-                               $params = array('user_id' => 
db_result($result,$i,'user_id'), 'size' => 's');
-                               plugin_hook("user_logo", $params);
+                               $params = array('user_id' => 
db_result($result,$i,'user_id'), 'size' => 's', 'content' => '');
+                               plugin_hook_by_reference("user_logo", $params);
+                               $return .= $params['content'];
 
-                               echo '<span style="float:left">';
-                               echo _('Date')._(': ').
+                               $return .= '<span style="float:left">';
+                               $return .= _('Date')._(': ').
                                        date(_('Y-m-d H:i'),db_result($result, 
$i, 'adddate')) .'<br />'.
                                        _('Sender')._(': ');
                                if(db_result($result,$i,'user_id') == 100) {
-                                       echo db_result($result,$i,'realname');
+                                       $return .= 
db_result($result,$i,'realname');
                                } else {
-                                       echo util_make_link_u 
(db_result($result,$i,'user_name'),db_result($result,$i,'user_id'),db_result($result,$i,'realname'));
+                                       $return .= util_make_link_u 
(db_result($result,$i,'user_name'),db_result($result,$i,'user_id'),db_result($result,$i,'realname'));
                                }
-                               echo '</span>';
+                               $return .= '</span>';
 
-                               echo '<p style="clear: both;padding-top: 
1em;">';
+                               $return .= '<p style="clear: both;padding-top: 
1em;">';
                                $text = db_result($result, $i, 'body');
                                $text = util_gen_cross_ref($text, 
$this->ArtifactType->Group->getID());
                                //$text = util_line_wrap( $text, 120,"\n");
                                $text = nl2br($text);
-                               echo $text;
-                               echo '</p>';
-                               echo '</td></tr>';
+                               $return .= $text;
+                               $return .= '</p>';
+                               $return .= '</td></tr>';
                        }
 
-                       echo '</tbody></table>';
+                       $return .= '</tbody></table>';
 
                } else {
-                       echo $HTML->information(_('No Comments Have Been 
Posted'));
+                       $return .= $HTML->information(_('No Comments Have Been 
Posted'));
                }
+               return $return;
        }
 
        function showHistory() {
                global $HTML;
                $result=$this->getHistory();
                $rows= db_numrows($result);
+               $return = '';
 
                if ($rows > 0) {
 
                        $title_arr=array();
-                       $title_arr[]=_('Field');
-                       $title_arr[]=_('Old Value');
-                       $title_arr[]=_('Date');
-                       $title_arr[]=_('By');
+                       $title_arr[] = _('Field');
+                       $title_arr[] = _('Old Value');
+                       //$title_arr[] = _('New Value');
+                       $title_arr[] = _('Date');
+                       $title_arr[] = _('By');
 
-                       echo $HTML->listTableTop($title_arr);
+                       $return .= $HTML->listTableTop($title_arr);
 
                        $artifactType =& $this->getArtifactType();
 
                        for ($i=0; $i < $rows; $i++) {
                                $field=db_result($result, $i, 'field_name');
-                               echo '
+                               $return .= '
                                <tr '. $HTML->boxGetAltRowStyle($i) 
.'><td>'.$field.'</td><td>';
 
                                if ($field == 'status_id') {
 
-                                       echo 
$artifactType->getStatusName(db_result($result, $i, 'old_value'));
+                                       $return .= 
$artifactType->getStatusName(db_result($result, $i, 'old_value'));
 
                                } elseif ($field == 'assigned_to') {
 
-                                       echo user_getname(db_result($result, 
$i, 'old_value'));
+                                       $return .= 
user_getname(db_result($result, $i, 'old_value'));
 
                                } elseif ($field == 'close_date') {
                                        if (db_result($result, $i, 'old_value'))
-                                               echo date(_('Y-m-d 
H:i'),db_result($result, $i, 'old_value'));
+                                               $return .= date(_('Y-m-d 
H:i'),db_result($result, $i, 'old_value'));
                                        else
-                                               echo '<i>'._('None').'</i>';
+                                               $return .= 
'<i>'._('None').'</i>';
                                } else {
 
-                                       echo db_result($result, $i, 
'old_value');
+                                       $return .= db_result($result, $i, 
'old_value');
 
                                }
-                               echo '</td>'.
+                               $return .= '</td>'.
                                        '<td>'. date(_('Y-m-d 
H:i'),db_result($result, $i, 'entrydate')) .'</td>'.
                                        '<td>'. db_result($result, $i, 
'user_name'). '</td></tr>';
                        }
 
-                       echo $HTML->listTableBottom();
+                       $return .= $HTML->listTableBottom();
 
                } else {
-                       echo $HTML->information(_('No Changes Have Been Made to 
This Item'));
+                       $return .= $HTML->information(_('No Changes Have Been 
Made to This Item'));
                }
-
+               return $return;
        }
 
        function showRelations() {
                $aid = $this->getID();
+               $return = '';
 
                // Search for all relations pointing to this record.
 
@@ -208,38 +215,36 @@ function hide_edit_button(id) {
                                              "% $aid %",
                                              "% $aid"));
                if (db_numrows($res)>0) {
-                       ?>
-<div id="tabber-relations" class="tabbertab">
-<table class="fullwidth">
-       <tr>
-               <td colspan="2">
-               <?php
-               $current = '';
-               $end = '';
-               while ($arr = db_fetch_array($res)) {
-                       if (forge_check_perm('tracker', 
$arr['group_artifact_id'], 'read')) {
-                               $title = $arr['group_name']._(': 
').$arr['name'];
-                               if ($title != $current) {
-                                       echo $end.'<strong>'.$title.'</strong>';
-                                       $current = $title;
-                                       $end = '<br /><br />';
-                               }
-                               $text = '[#'.$arr['artifact_id'].']'.' 
'.$arr['summary'];
-                               $url = 
'/tracker/?func=detail&aid='.$arr['artifact_id'].'&group_id='.$arr['group_id'].'&atid='.$arr['group_artifact_id'];
-                               $arg['title'] = 
util_html_secure($arr['summary']);
-                               if ($arr['status_id'] == 2) {
-                                       $arg['class'] = 'artifact_closed';
+                       $return = '<div id="tabber-relations" class="tabbertab">
+                                       <table class="fullwidth">
+                                               <tr>
+                                                       <td colspan="2">';
+                       $current = '';
+                       $end = '';
+                       while ($arr = db_fetch_array($res)) {
+                               if (forge_check_perm('tracker', 
$arr['group_artifact_id'], 'read')) {
+                                       $title = $arr['group_name']._(': 
').$arr['name'];
+                                       if ($title != $current) {
+                                               $return .= 
$end.'<strong>'.$title.'</strong>';
+                                               $current = $title;
+                                               $end = '<br /><br />';
+                                       }
+                                       $text = '[#'.$arr['artifact_id'].']'.' 
'.$arr['summary'];
+                                       $url = 
'/tracker/?func=detail&aid='.$arr['artifact_id'].'&group_id='.$arr['group_id'].'&atid='.$arr['group_artifact_id'];
+                                       $arg['title'] = 
util_html_secure($arr['summary']);
+                                       if ($arr['status_id'] == 2) {
+                                               $arg['class'] = 
'artifact_closed';
+                                       }
+                                       $return .= '<br/>&nbsp;&nbsp;&nbsp;';
+                                       $return .= util_make_link($url, $text, 
$arg).' <i>('._('Relation')._(': ').$arr['field_name'].')</i>';
                                }
-                               print '<br/>&nbsp;&nbsp;&nbsp;';
-                               echo util_make_link($url, $text, $arg).' 
<i>('._('Relation')._(': ').$arr['field_name'].')</i>';
                        }
+                       $return .= '</td>
+                               </tr>
+                               </table>
+                               </div>';
                }
-               ?></td>
-       </tr>
-</table>
-</div>
-<?php
-               }
+               return $return;
        }
 }
 
diff --git a/src/common/tracker/include/ArtifactTypeHtml.class.php 
b/src/common/tracker/include/ArtifactTypeHtml.class.php
index 370b1e7..3d3e329 100644
--- a/src/common/tracker/include/ArtifactTypeHtml.class.php
+++ b/src/common/tracker/include/ArtifactTypeHtml.class.php
@@ -361,6 +361,8 @@ class ArtifactTypeHtml extends ArtifactType {
                        return;
                }
 
+               $return = '';
+
                $taskcount = db_numrows($ah->getRelatedTasks());
                db_result_reset($ah->getRelatedTasks());
 
@@ -371,7 +373,6 @@ class ArtifactTypeHtml extends ArtifactType {
                }
 
                $totalPercentage = 0;
-               echo '<tr><td colspan="2">';
                if ($taskcount > 0) {
                        $title_arr = array();
                        $title_arr[] = _('Task Id and Summary');
@@ -380,7 +381,7 @@ class ArtifactTypeHtml extends ArtifactType {
                        $title_arr[] = _('End Date');
                        $title_arr[] = _('Status');
                        (($is_admin) ? $title_arr[]=_('Remove Relation') : '');
-                       echo $HTML->listTableTop($title_arr);
+                       $return .= $HTML->listTableTop($title_arr);
 
                        for ($i = 0; $i < $taskcount; $i++) {
                                $taskinfo  = db_fetch_array($ah->relatedtasks, 
$i);
@@ -393,7 +394,7 @@ class ArtifactTypeHtml extends ArtifactType {
                                        $startdate = date(_('Y-m-d H:i'), 
$taskinfo['start_date']);
                                        $enddate   = date(_('Y-m-d H:i'), 
$taskinfo['end_date']);
                                        $status   = $taskinfo['status_name'];
-                                       echo '<tr>
+                                       $return .=  '<tr>
                                                        
<td>'.util_make_link('/pm/task.php?func=detailtask&project_task_id='.$taskid.'&group_id='.$groupid.'&group_project_id='.$projectid,
 '[T'.$taskid.'] '.$summary).'</td>
                                                        <td><div 
class="percentbar" style="width: 100px;">
                                                                <div 
style="width:'.round($taskinfo['percent_complete']).'px;"></div></div></td>
@@ -404,51 +405,51 @@ class ArtifactTypeHtml extends ArtifactType {
                                                '</tr>';
                                }
                        }
-                       echo $HTML->listTableBottom();
+                       $return .=  $HTML->listTableBottom();
 
-                       echo "\n<hr /><p style=\"text-align:right;\">";
-                       echo _('Average completion rate')._(': 
').(int)($totalPercentage/$taskcount).'%';
-                       echo "</p>\n";
+                       $return .=  "\n<hr /><p style=\"text-align:right;\">";
+                       $return .=  _('Average completion rate')._(': 
').(int)($totalPercentage/$taskcount).'%';
+                       $return .=  "</p>\n";
                } else {
-                       echo $HTML->information(_('No related tasks'));
+                       $return .=  $HTML->information(_('No related tasks'));
                }
-               echo '</td></tr>';
+               return $return;
        }
 
        function renderFiles($group_id, $ah) {
                global $HTML;
                $file_list =& $ah->getFiles();
                $count=count($file_list);
-
+               $return = '';
                if ($count > 0) {
-                       echo '<tr><td colspan="2">';
-                       echo '<b>'._("Attachments")._(':').'</b>'.'<br/>';
+
+                       $return .= 
'<strong>'._("Attachments")._(':').'</strong>'.'<br/>';
                        $title_arr=array();
                        $title_arr[] = _('Size');
                        $title_arr[] = _('Name');
                        $title_arr[] = _('Date');
                        $title_arr[] = _('By');
                        $title_arr[] = _('Download');
-                       echo $HTML->listTableTop($title_arr);
+                       $return .= $HTML->listTableTop($title_arr);
 
                        foreach ($file_list as $file) {
-                               echo '<tr>';
-                               echo 
'<td>'.human_readable_bytes($file->getSize()).'</td>';
-                               echo 
'<td>'.htmlspecialchars($file->getName()).'</td>';
-                               echo '<td>'.date(_('Y-m-d H:i'), 
$file->getDate()).'</td>';
-                               echo 
'<td>'.$file->getSubmittedUnixName().'</td>';
-                               echo 
'<td>'.util_make_link('/tracker/download.php/'.$group_id.'/'. 
$this->getID().'/'. $ah->getID() .'/'.$file->getID().'/'.$file->getName(), 
htmlspecialchars($file->getName())).'</td>';
+                               $return .= '<tr>';
+                               $return .= 
'<td>'.human_readable_bytes($file->getSize()).'</td>';
+                               $return .= 
'<td>'.htmlspecialchars($file->getName()).'</td>';
+                               $return .= '<td>'.date(_('Y-m-d H:i'), 
$file->getDate()).'</td>';
+                               $return .= 
'<td>'.$file->getSubmittedUnixName().'</td>';
+                               $return .= 
'<td>'.util_make_link('/tracker/download.php/'.$group_id.'/'. 
$this->getID().'/'. $ah->getID() .'/'.$file->getID().'/'.$file->getName(), 
htmlspecialchars($file->getName())).'</td>';
                                if (forge_check_perm ('tracker', 
$this->getID(), 'tech')) {
-                                       echo '<td><input type="checkbox" 
name="delete_file[]" value="'. $file->getID() .'">'._('Delete').'</td>';
+                                       $return .= '<td><input type="checkbox" 
name="delete_file[]" value="'. $file->getID() .'">'._('Delete').'</td>';
                                }
-                               echo '</tr>';
+                               $return .= '</tr>';
                        }
 
-                       echo $HTML->listTableBottom();
-                       echo '</td></tr>';
+                       $return .= $HTML->listTableBottom();
                } else {
-                       echo $HTML->information(_('No attached documents'));
+                       $return .= $HTML->information(_('No attached 
documents'));
                }
+               return $return;
        }
 
        /**
@@ -472,7 +473,7 @@ class ArtifactTypeHtml extends ArtifactType {
         * generateRenderHTML
         *
         * @param       array   $types
-        * @param       string  $mode   Display mode (QUERY OR DISPLAY)
+        * @param       string  $mode   Display mode (QUERY OR DISPLAY OR NEW)
         * @return      string  HTML template.
         */
        function generateRenderHTML($types=array(), $mode) {
@@ -623,7 +624,6 @@ class ArtifactTypeHtml extends ArtifactType {
                if ($show_100 && !empty($aefChildren)) {
                        $attrs_100 = array( 'data-dependency'=>'{"fields": 
['.implode(', ',$aefChildren).']}');
                }
-
                return html_build_select_box_from_arrays 
($vals,$texts,'extra_fields['.$extra_field_id.']',$checked,$show_100,$text_100,$show_any,$text_any,
 $allowed, $attrs, $opt_attrs, $attrs_100);
        }
 
@@ -967,7 +967,7 @@ class ArtifactTypeHtml extends ArtifactType {
                return html_e('textarea', 
array_merge(array('name'=>'extra_fields['.$extra_field_id.']', 'rows'=>$rows, 
'cols'=>$cols), $attrs), $contents, false);
        }
 
-       
+
        /**
         * renderDatetime - this function builds a Datetime field.
         *
@@ -976,11 +976,10 @@ class ArtifactTypeHtml extends ArtifactType {
         * @param       array   $attrs          Array of other attributes
         * @return      string  datetime.
         */
-       function renderDatetime($extra_field_id,$datetime, $attrs = array()) {
-               $return .= html_e('input', array_merge(array('type'=>'text', 
'class'=>'datetimepicker'),$attrs));
-               return $return;
+       function renderDatetime($extra_field_id, $datetime, $attrs = array()) {
+               return html_e('input', array_merge(array('type'=>'text', 
'class'=>'datetimepicker'), $attrs));
        }
-       
+
        function technicianBox 
($name='assigned_to[]',$checked='xzxz',$show_100=true,$text_100='none',$extra_id='-1',$extra_name='',$multiple=false)
 {
                if ($text_100=='none'){
                        $text_100=_('Nobody');
diff --git a/src/common/tracker/views/form-addextrafield.php 
b/src/common/tracker/views/form-addextrafield.php
index 9cef46e..53685fd 100644
--- a/src/common/tracker/views/form-addextrafield.php
+++ b/src/common/tracker/views/form-addextrafield.php
@@ -323,10 +323,12 @@ echo html_ac(html_ap() - 1);
 echo $HTML->closeForm();
 
 echo html_e('h2', array(), _('Custom Field Rendering Template'));
-echo html_ao('p');
-echo 
util_make_link('/tracker/admin/?edittemplate=1&group_id='.$group_id.'&atid='.$ath->getID(),
 _('Edit template')).html_e('br');
-echo 
util_make_link('/tracker/admin/?deletetemplate=1&group_id='.$group_id.'&atid='.$ath->getID(),
 _('Delete template'));
-echo html_ac(html_ap() - 1);
+if (forge_get_config('use_tracker_widget_display')) {
+       echo $HTML->warning_msg(_('You have to use widgets to render 
extrafields on submit/update artifact. Click on submit new to get access to 
layout update.'));
+} else {
+       echo html_e('p', array(), 
util_make_link('/tracker/admin/?edittemplate=1&group_id='.$group_id.'&atid='.$ath->getID(),
 _('Edit template')).html_e('br')
+                               
.util_make_link('/tracker/admin/?deletetemplate=1&group_id='.$group_id.'&atid='.$ath->getID(),
 _('Delete template')));
+}
 
 $ath->footer();
 
diff --git a/src/common/widget/Widget.class.php 
b/src/common/widget/Widget.class.php
index 79a03d6..8fb0388 100644
--- a/src/common/widget/Widget.class.php
+++ b/src/common/widget/Widget.class.php
@@ -1,7 +1,7 @@
 <?php
 /**
  * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights 
reserved
- * Copyright 2012,2014,2016 Franck Villaume - TrivialDev
+ * Copyright 2012,2014,2016, Franck Villaume - TrivialDev
  *
  * This file is a part of Fusionforge.
  *
@@ -58,6 +58,13 @@ require_once $gfcommon.'widget/Widget_HomeStats.class.php';
 require_once $gfcommon.'widget/Widget_HomeTagCloud.class.php';
 require_once $gfcommon.'widget/Widget_HomeVersion.class.php';
 
+require_once $gfcommon.'widget/Widget_TrackerComment.class.php';
+require_once $gfcommon.'widget/Widget_TrackerContent.class.php';
+require_once $gfcommon.'widget/Widget_TrackerDefaultActions.class.php';
+require_once $gfcommon.'widget/Widget_TrackerGeneral.class.php';
+require_once $gfcommon.'widget/Widget_TrackerMain.class.php';
+require_once $gfcommon.'widget/Widget_TrackerSummary.class.php';
+
 /**
  * FusionForge Layout Widget
  */
@@ -278,6 +285,24 @@ require_once 
$gfcommon.'widget/Widget_HomeVersion.class.php';
                        case 'projectlatestcommits':
                                $o = new Widget_ProjectLatestCommits();
                                break;
+                       case 'trackercontent':
+                               $o = new Widget_TrackerContent();
+                               break;
+                       case 'trackercomment':
+                               $o = new Widget_TrackerComment();
+                               break;
+                       case 'trackerdefaultactions':
+                               $o = new Widget_TrackerDefaultActions();
+                               break;
+                       case 'trackergeneral':
+                               $o = new Widget_TrackerGeneral();
+                               break;
+                       case 'trackermain':
+                               $o = new Widget_TrackerMain();
+                               break;
+                       case 'trackersummary':
+                               $o = new Widget_TrackerSummary();
+                               break;
                        default:
                                //$em = EventManager::instance();
                                //$em->processEvent('widget_instance', 
array('widget' => $widget_name, 'instance' => &$o));
@@ -313,6 +338,9 @@ require_once 
$gfcommon.'widget/Widget_HomeVersion.class.php';
                        case WidgetLayoutManager::OWNER_TYPE_HOME:
                                $widgets = array('hometagcloud', 'homeversion', 
'homelatestnews', 'homestats', 'homedetailactivitymostactiveprojectweek');
                                break;
+                       case WidgetLayoutManager::OWNER_TYPE_TRACKER:
+                               $widgets = array('trackercontent', 
'trackercomment', 'trackerdefaultactions', 'trackergeneral', 'trackermain', 
'trackersummary');
+                               break;
                        default:
                                $widgets = array();
                                break;
@@ -359,4 +387,12 @@ require_once 
$gfcommon.'widget/Widget_HomeVersion.class.php';
        function getIframeUrl($owner_id, $owner_type) {
                return '/widgets/widget.php?owner='. $owner_type.$owner_id 
.'&amp;action=iframe&amp;name%5B'. $this->id .'%5D='. $this->getInstanceId();
        }
+
+       function canBeMinize() {
+               return true;
+       }
+
+       function canBeRemove() {
+               return true;
+       }
 }
diff --git a/src/common/widget/WidgetLayoutManager.class.php 
b/src/common/widget/WidgetLayoutManager.class.php
index cacd9ba..89b2804 100644
--- a/src/common/widget/WidgetLayoutManager.class.php
+++ b/src/common/widget/WidgetLayoutManager.class.php
@@ -30,18 +30,19 @@ require_once $gfcommon.'include/preplugins.php';
  * Manage layouts for users, groups and homepage
  */
 class WidgetLayoutManager {
-       const OWNER_TYPE_USER  = 'u';
+
        /**
-        * Layout for project home
-        * @var string
+        * define constants for type of widget page
         */
-       const OWNER_TYPE_GROUP = 'g';
-       const OWNER_TYPE_HOME  = 'h';
+       const OWNER_TYPE_USER    = 'u';
+       const OWNER_TYPE_GROUP   = 'g';
+       const OWNER_TYPE_HOME    = 'h';
+       const OWNER_TYPE_TRACKER = 't';
 
        /**
         * displayLayout
         *
-        * Display the default layout for the "owner". It may be the home page, 
the project summary page or /my/ page.
+        * Display the default layout for the "owner". It may be the home page, 
the project summary page, the project tracker artifact view page, or /my/ page.
         *
         * @param       int     $owner_id
         * @param       string  $owner_type
@@ -59,6 +60,9 @@ class WidgetLayoutManager {
                        } elseif ($owner_type == self::OWNER_TYPE_HOME) {
                                $this->createDefaultLayoutForForge($owner_id);
                                $this->displayLayout($owner_id, $owner_type);
+                       } elseif ($owner_type == self::OWNER_TYPE_TRACKER) {
+                               $this->createDefaultLayoutForTracker($owner_id);
+                               $this->displayLayout($owner_id, $owner_type);
                        }
                } else {
                        $sql = "SELECT l.*
@@ -108,28 +112,33 @@ class WidgetLayoutManager {
         * @return      boolean true if the user can update the layout 
(add/remove widget, collapse, set preferences, ...)
         */
        function _currentUserCanUpdateLayout($owner_id, $owner_type) {
-               $readonly = true;
+               $modify = false;
                $request =& HTTPRequest::instance();
                switch ($owner_type) {
                        case self::OWNER_TYPE_USER:
                                if (user_getid() == $owner_id) { //Current user 
can only update its own /my/ page
-                                       $readonly = false;
+                                       $modify = true;
                                }
                                break;
                        case self::OWNER_TYPE_GROUP:
-                               if (forge_check_perm('project_admin', 
$owner_id, NULL)) { //Only project admin
-                                       $readonly = false;
+                               if (forge_check_perm('project_admin', 
$owner_id)) { //Only project admin
+                                       $modify = true;
                                }
                                break;
                        case self::OWNER_TYPE_HOME:
                                if (forge_check_global_perm('forge_admin')) { 
//Only site admin
-                                       $readonly = false;
+                                       $modify = true;
+                               }
+                               break;
+                       case self::OWNER_TYPE_TRACKER:
+                               if (forge_check_global_perm('tracker_admin', 
$owner_id)) { //Only tracker admin
+                                       $modify = true;
                                }
                                break;
                        default:
                                break;
                }
-               return !$readonly;
+               return $modify;
        }
        /**
         * createDefaultLayoutForUser
@@ -146,11 +155,10 @@ class WidgetLayoutManager {
         * @param       int     $owner_id The id of the newly created user
         */
        function createDefaultLayoutForUser($owner_id) {
-               $owner_type = self::OWNER_TYPE_USER;
                db_begin();
                $success = true;
                $sql = "INSERT INTO owner_layouts(layout_id, is_default, 
owner_id, owner_type) VALUES (1, 1, $1, $2)";
-               if (db_query_params($sql, array($owner_id, $owner_type))) {
+               if (db_query_params($sql, array($owner_id, 
self::OWNER_TYPE_USER))) {
 
                        $sql = "INSERT INTO layouts_contents(owner_id, 
owner_type, layout_id, column_id, name, rank) VALUES ";
 
@@ -162,7 +170,7 @@ class WidgetLayoutManager {
                        $args[] = "($1, $2, 1, 2, 'mymonitoredfp', 1)";
 
                        foreach($args as $a) {
-                               if 
(!db_query_params($sql.$a,array($owner_id,$owner_type))) {
+                               if (!db_query_params($sql.$a,array($owner_id, 
self::OWNER_TYPE_USER))) {
                                        $success = false;
                                        break;
                                }
@@ -170,7 +178,7 @@ class WidgetLayoutManager {
 
                        /*  $em =& EventManager::instance();
                            $widgets = array();
-                           $em->processEvent('default_widgets_for_new_owner', 
array('widgets' => &$widgets, 'owner_type' => $owner_type));
+                           $em->processEvent('default_widgets_for_new_owner', 
array('widgets' => &$widgets, 'owner_type' => self::OWNER_TYPE_USER));
                            foreach($widgets as $widget) {
                            $sql .= ",($13, $14, 1, $15, $16, $17)";
                            }*/
@@ -214,6 +222,60 @@ class WidgetLayoutManager {
                db_commit();
        }
 
+       function createDefaultLayoutForTracker($owner_id) {
+               db_begin();
+               $success = true;
+               $sql = "INSERT INTO owner_layouts (owner_id, owner_type, 
layout_id, is_default) values ($1, $2, $3, $4)";
+               if (db_query_params($sql, array($owner_id, 
self::OWNER_TYPE_TRACKER, 1, 1))) {
+
+                       $sql = "INSERT INTO layouts_contents (owner_id, 
owner_type, layout_id, column_id, name, rank) VALUES ";
+
+                       $args[] = "($1, $2, 1, 1, 'trackersummary', 1)";
+                       $args[] = "($1, $2, 1, 1, 'trackermain', 2)";
+                       $args[] = "($1, $2, 1, 1, 'trackerdefaultactions', 3)";
+                       $args[] = "($1, $2, 1, 2, 'trackergeneral', 1)";
+                       $args[] = "($1, $2, 1, 2, 'trackercomment', 2)";
+
+                       // owner_id is an atid
+                       $at = artifactType_get_object($owner_id);
+                       $extrafields = $at->getExtraFields(array());
+                       if (count($extrafields) > 0) {
+
+                       }
+
+                       foreach($args as $a) {
+                               if (!db_query_params($sql.$a,array($owner_id, 
self::OWNER_TYPE_TRACKER))) {
+                                       $success = false;
+                                       break;
+                               }
+                       }
+
+                       if (count($extrafields) > 0) {
+                               $res = db_query_params('INSERT INTO 
artifact_display_widget (owner_id, title, cols) VALUES ($1, $2, $3)', 
array($owner_id, _('Default ExtraField 2-columns Widget'), 2));
+                               $content_id = db_insertid($res, 
'artifact_display_widget', 'id');
+                               $row_id = 1;
+                               $column_id = 1;
+                               foreach ($extrafields as $key => $extrafield) {
+                                       $column_id = ($key % 2) + 1; // 1 or 2
+                                       if ($column_id == 2) {
+                                               $row_id++;
+                                       }
+                                       db_query_params('INSERT INTO 
artifact_display_widget_field (id, field_id, column_id, row_id) VALUES ($1, $2, 
$3, $4)', array($content_id, $extrafield['extra_field_id'], $column_id, 
$row_id));
+                               }
+                               db_query_params('INSERT INTO layouts_contents 
(owner_id, owner_type, layout_id, column_id, name, rank, content_id) VALUES 
($1, $2, 1, 2, $3, 3, $4)',
+                                               array($owner_id, 
self::OWNER_TYPE_TRACKER, 'trackercontent', $content_id));
+                       }
+               } else {
+                       $success = false;
+               }
+               if (!$success) {
+                       $success = db_error();
+                       db_rollback();
+                       exit_error(sprintf(_('DB Error: %s'), $success), 
'widgets');
+               }
+               db_commit();
+       }
+
        /**
         * createDefaultLayoutForProject
         *
@@ -705,6 +767,7 @@ class WidgetLayoutManager {
         * @param       object  $widget
         */
        function removeWidget($owner_id, $owner_type, $layout_id, $name, 
$instance_id, &$widget) {
+               
error_log('o='.$owner_id.',t='.$owner_type.',layout_id='.$layout_id.',instance_id='.$instance_id);
                $sql = "DELETE FROM layouts_contents WHERE owner_type =$1 AND 
owner_id = $2 AND layout_id = $3 AND name = $4 AND content_id = $5";
                
db_query_params($sql,array($owner_type,$owner_id,$layout_id,$name,$instance_id));
                if (!db_error()) {
diff --git a/src/common/widget/Widget_TrackerComment.class.php 
b/src/common/widget/Widget_TrackerComment.class.php
new file mode 100644
index 0000000..24d69bf
--- /dev/null
+++ b/src/common/widget/Widget_TrackerComment.class.php
@@ -0,0 +1,185 @@
+<?php
+/**
+ * Comment Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+
+class Widget_TrackerComment extends Widget {
+
+       var $content;
+
+       function __construct() {
+               $request =& HTTPRequest::instance();
+               $owner_id   = (int)substr($request->get('owner'), 1);
+               parent::__construct('trackercomment', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+               $this->content['title'] = _('Follow-up tabs');
+       }
+
+       function getTitle() {
+               return $this->content['title'];
+       }
+
+       function getDescription() {
+               return _('Default widget where comments, attachments, ... tabs 
are stored & displayed.');
+       }
+
+       function isAvailable() {
+               return isset($this->content['title']);
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               global $func;
+               $return = '';
+               if ($func == 'detail') {
+                       $count = $ah->hasMessages();
+                       $nb = $count? ' ('.$count.')' : '';
+                       $file_list = $ah->getFiles();
+                       $count=count($file_list);
+               }
+               $nbf = (isset($count) && $count)? ' ('.$count.')' : '';
+               $elementsLi = array();
+               if ($func == 'detail') {
+                       $elementsLi[] = array('content' => 
util_make_link('#tabber-comments', _('Comments').$nb, false, true));
+                       if ($group->usesPM()) {
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-tasks', _('Related Tasks'), false, true));
+                       }
+               }
+               $elementsLi[] = array('content' => 
util_make_link('#tabber-attachments', _('Attachments').$nbf, false, true));
+               $pluginfound = false;
+               if ($func == 'detail') {
+                       $pm = plugin_manager_get_object();
+                       $pluginsListeners = 
$pm->GetHookListeners('artifact_extra_detail');
+
+                       foreach ($pluginsListeners as $pluginsListener) {
+                               if ($group->usesPlugin($pluginsListener)) {
+                                       $pluginfound = true;
+                                       break;
+                               }
+                       }
+                       if ($pluginfound) {
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-commits', _('Commits'), false, true));
+                       }
+                       $elementsLi[] = array('content' => 
util_make_link('#tabber-changes', _('Changes'), false, true));
+                       if ($ah->hasRelations()) {
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-relations', _('Relations'), false, true));
+                       }
+                       if (forge_get_config('use_object_associations')) {
+                               $tabTitle = _('Associations');
+                               if ($ah->getAssociationCounter()) {
+                                       $tabTitle .= ' 
('.$ah->getAssociationCounter().')';
+                               }
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-associations', $tabTitle, false, true));
+                       }
+               }
+               $tabberContent = '';
+               if ($func == 'detail') {
+                       $divContent = '';
+                       if (forge_check_perm('tracker', $atid, 'tech')) {
+                               $divContent .= html_e('strong', array(), _('Use 
Canned Response')._(':')).html_e('br').
+                                               
$ath->cannedResponseBox('canned_response').' 
'.util_make_link('/tracker/admin/?group_id='.$group_id.'&atid='.$ath->getID().'&add_canned=1',
 '('._('Admin').')').html_e('br').
+                                               '<script 
type="text/javascript">//<![CDATA[
+                                                       
jQuery("#tracker-canned_response").change(function() {
+                                                               jQuery.ajax({
+                                                                       type: 
"POST",
+                                                                       url: 
"index.php",
+                                                                       data: 
"rtype=ajax&function=get_canned_response&group_id='.$group_id.'&canned_response_id="+jQuery("#tracker-canned_response").val(),
+                                                                       
success: function(rep){
+                                                                               
// the following line is not the best but works with IE6
+                                                                               
jQuery("#tracker-canned_response option").each(function() 
{jQuery(this).attr("selected", "selected"); return false;});
+                                                                               
if (jQuery("#tracker-comment").val()) {
+                                                                               
        rep = "\n" + rep
+                                                                               
}
+                                                                               
jQuery("#tracker-comment").val(jQuery("#tracker-comment").val() + rep);
+                                                                       }
+                                                               });
+                                                       });
+                                               //]]></script>';
+                       }
+                       if (forge_check_perm('tracker', $atid, 'submit')) {
+                               $divContent .= html_e('strong', array(), 
_('Post Comment')._(':')).html_e('br').
+                                               html_e('textarea', array('id' 
=> 'tracker-comment', 'name' => 'details', 'rows' => 7, 'style' => 'width: 
100%', 'title' => util_html_secure(html_get_tooltip_description('comment'))), 
'', false);
+                       }
+                       $tabberContent .= html_e('div', array('id' => 
'tabber-comments', 'class' => 'tabbertab'), $divContent.$ah->showMessages());
+                       if ($group->usesPM()) {
+                               $tabberContent .= html_e('div', array('id' => 
'tabber-tasks', 'class' => 'tabbertab'),
+                                                       
$ath->renderRelatedTasks($group, $ah).
+                                                       
util_make_link('/tracker/?func=taskmgr&group_id='.$group_id.'&atid='.$atid.'&aid='.$aid,
 html_image('ic/taskman20w.png', 20, 20).'<strong>'._('Build Task 
Relation').'</strong>'));
+                       }
+               }
+               $attachmentContent = '';
+               if (forge_check_perm('tracker', $atid, 'submit')) {
+                       $attachmentContent .=  html_e('strong', array(), 
_('Attach Files')._(':')).' ('._('max upload size')._(': 
').human_readable_bytes(util_get_maxuploadfilesize()).')'.html_e('br');
+                       for ($i = 0; $i < 5; $i++) {
+                               $attachmentContent .= html_e('input', 
array('type' => 'file', 'name' => 'input_file'.$i, 'size' => 30)).html_e('br');
+                       }
+               }
+               if ($func == 'detail') {
+                       $attachmentContent .= $ath->renderFiles($group_id, $ah);
+               }
+
+               $tabberContent .= html_e('div', array('id' => 
'tabber-attachments', 'class' => 'tabbertab'),
+                                               $attachmentContent, false);
+               if ($pluginfound) {
+                       //TODO: implement it!!!
+                       $tabberContent .= html_e('div', array('id' => 
'tabber-commits', 'class' => 'tabbertab'),
+                                                       '', false);
+               }
+               if ($func == 'detail') {
+                       $tabberContent .= html_e('div', array('id' => 
'tabber-changes', 'class' => 'tabbertab'),
+                                               $ah->showHistory());
+                       $tabberContent .= $ah->showRelations();
+                       if (forge_get_config('use_object_associations')) {
+                               $associationContent = 
$ah->showAssociations('/tracker/?func=removeassoc&aid='.$ah->getID().'&group_id='.$group_id.'&atid='.$ath->getID());
+                               if (forge_check_perm('tracker', $atid, 'tech')) 
{
+                                       $associationContent .= 
$ah->showAddAssociations();
+                               }
+                               $tabberContent .= html_e('div', array('id' => 
'tabber-associations', 'class' => 'tabbertab'), $associationContent);
+                       }
+               }
+               $return .= html_e('div', array('id' => 'tabber'), 
$HTML->html_list($elementsLi).$tabberContent);
+
+               if (forge_check_perm('tracker', $atid, 'submit')) {
+                       $return .= html_e('p', array('class' => 'middleRight'), 
html_e('input', array('type' => 'submit', 'name' => 'submit', 'value' => 
_('Save Changes'))));
+               }
+               return $return;
+       }
+
+       function canBeRemove() {
+               return false;
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+}
+
diff --git a/src/common/widget/Widget_TrackerContent.class.php 
b/src/common/widget/Widget_TrackerContent.class.php
new file mode 100644
index 0000000..e0b2e79
--- /dev/null
+++ b/src/common/widget/Widget_TrackerContent.class.php
@@ -0,0 +1,438 @@
+<?php
+/**
+ * Generic Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+require_once $gfwww.'include/jquery_plugins.php';
+
+class Widget_TrackerContent extends Widget {
+       var $trackercontent_title;
+       var $trackercolumns;
+
+       function __construct() {
+               $request =& HTTPRequest::instance();
+               $owner_id = (int)substr($request->get('owner'), 1);
+               if (!$owner_id) {
+                       $owner_id = (int)$request->get('atid');
+               }
+               parent::__construct('trackercontent', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+               $this->setOwner($owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+       }
+
+       function getTitle() {
+               $hp = Codendi_HTMLPurifier::instance();
+               return $this->trackercontent_title ? 
$hp->purify($this->trackercontent_title, CODENDI_PURIFIER_CONVERT_HTML)  : 
_('Tracker Content Box');
+       }
+
+       function isUnique() {
+               return false;
+       }
+
+       function isAvailable() {
+               return true;
+       }
+
+       function getDescription() {
+               return _("Create an empty widget to link fields together and 
then organize the artifact display view (update & submit new).");
+       }
+
+       function loadContent($id) {
+               $this->content_id = $id;
+               $this->trackercontent_title = $this->getTitleBlock($id);
+       }
+
+       function getTitleBlock($id) {
+               $res = db_query_params('select title from 
artifact_display_widget where id = $1', array($id));
+               $title = false;
+               if ($res) {
+                       $arr = db_fetch_array($res);
+                       $title = $arr[0];
+               }
+               return $title;
+       }
+
+       function create(&$request) {
+               $hp = Codendi_HTMLPurifier::instance();
+               $this->trackercontent_title = 
$hp->purify($request->get('title'), CODENDI_PURIFIER_CONVERT_HTML);
+               $this->trackercolumns = (int)$request->get('columns');
+               $res = db_query_params('INSERT INTO artifact_display_widget 
(owner_id, title, cols) VALUES ($1, $2, $3)', array($this->owner_id, 
$this->trackercontent_title, $this->trackercolumns));
+               $content_id = db_insertid($res, 'artifact_display_widget', 
'id');
+               $extrafieldIDs = getArrayFromRequest('extrafieldids');
+               $extrafieldIDColumns = 
getArrayFromRequest('extrafield_column_ids');
+               $extrafieldIDRows = getArrayFromRequest('extrafield_row_ids');
+               foreach ($extrafieldIDs as $key => $extrafieldID) {
+                       db_query_params('INSERT INTO 
artifact_display_widget_field (id, field_id, column_id, row_id) VALUES ($1, $2, 
$3, $4)', array($content_id, $extrafieldID, $extrafieldIDColumns[$key], 
$extrafieldIDRows[$key]));
+               }
+               return $content_id;
+       }
+
+       function destroy($id) {
+               db_query_params('DELETE FROM artifact_display_widget WHERE id = 
$1 AND owner_id = $2',array($id, $this->owner_id));
+               db_query_params('DELETE FROM artifact_display_widget_field 
WHERE id = $1', array($id));
+       }
+
+       private function getPartialPreferencesFormTitle($title) {
+               return html_e('p', array(), _('Title')._(':').html_e('input', 
array('type' => 'text', 'name' => 'title', 'size' => 30, 'value' => 
htmlspecialchars($title))));
+       }
+
+       private function getPartialPreferencesFormColumns($column_number) {
+               return html_e('p', array(), _('Number of vertical 
columns')._(':').html_e('input', array('type' => 'number', 'name' => 'columns', 
'value' => $column_number, 'step' => 1, 'min' => 1, 'title' => _('Set number of 
columns to split your box into columns'))));
+       }
+
+       private function getExtraFieldsForm($owner_id) {
+               global $HTML;
+               $atid = $owner_id;
+               $artifactTypeObject = artifactType_get_object($atid);
+               $availableExtraFields = $artifactTypeObject->getExtraFields();
+               $stillAvailableExtraFields = 
$this->availableExtrafields($owner_id, $availableExtraFields);
+               $content = html_e('p', array(), sprintf(_('Tick available 
ExtraFields from %s to display into this widget'), 
$artifactTypeObject->getName())._(':'));
+               if (count($stillAvailableExtraFields) > 0) {
+                       $content .= $HTML->listTableTop(array('', '', _('Column 
ID'), _('Row ID')));
+                       foreach ($stillAvailableExtraFields as $key => 
$stillAvailableExtraField) {
+                               $cells = array();
+                               $cells[][] = 
util_unconvert_htmlspecialchars($stillAvailableExtraField['field_name']);
+                               $cells[][] = html_e('input', array('type' => 
'checkbox', 'name' => 'extrafieldids[]', 'value' => 
$stillAvailableExtraField[0]));
+                               $cells[][] = html_e('input', array('type' => 
'number', 'name' => 'extrafield_column_ids[]', 'value' => 1, 'step' => 1, 'min' 
=> 1, 'title' => _('Set the column number accordingly to the number of columns 
you created')));
+                               $cells[][] = html_e('input', array('type' => 
'number', 'name' => 'extrafield_row_ids[]', 'value' => 1, 'step' => 1, 'min' => 
1, 'title' => _('Set the row number accordingly to organize the extrafields')));
+                               $content .= $HTML->multiTableRow(array('class' 
=> $HTML->boxGetAltRowStyle($key, true)), $cells);
+                       }
+                       $content .= $HTML->listTableBottom();
+               }
+               return $content;
+       }
+
+       private function availableExtrafields($owner_id, $extrafields) {
+               $arr = $this->getExtraFieldIDs($owner_id);
+               $availableExtrafields = array();
+               foreach ($extrafields as $extrafield) {
+                       if (!in_array($extrafield[0], $arr)) {
+                               $availableExtrafields[] = $extrafield;
+                       }
+               }
+               return $availableExtrafields;
+       }
+
+       private function getExtraFieldIDs($id) {
+               $res = db_query_params('select field_id from 
artifact_display_widget_field, artifact_display_widget
+                                       where artifact_display_widget_field.id 
= artifact_display_widget.id and artifact_display_widget.owner_id = $1', 
array($id));
+               $extrafieldIDs = array();
+               if ($res) {
+                       $extrafieldIDs = util_result_column_to_array($res, 0);
+               }
+               return $extrafieldIDs;
+       }
+
+       private function getLayoutExtraFieldIDs($id) {
+               $res = db_query_params('select row_id, column_id, field_id from 
artifact_display_widget_field where id = $1 order by row_id, column_id', 
array($id));
+               $extrafieldIDs = array();
+               if ($res && (db_numrows($res) > 0)) {
+                       while ($arr = db_fetch_array($res)) {
+                               $extrafieldIDs[$arr[0]][$arr[1]][] = $arr[2];
+                       }
+               }
+               return $extrafieldIDs;
+       }
+
+       function getInstallPreferences() {
+               $request =& HTTPRequest::instance();
+               $owner_id = (int)substr($request->get('owner'), 1);
+               $content = $this->getPartialPreferencesFormTitle(_('Enter title 
of Tracker Content Box'));
+               $content .= $this->getPartialPreferencesFormColumns(1);
+               $content .= $this->getExtraFieldsForm($owner_id);
+               return $content;
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               global $func;
+
+               //manage redirect in case of missing required fields
+               global $extra_fields;
+
+               $return = '';
+               $layoutExtraFieldIDs = 
$this->getLayoutExtraFieldIDs($this->content_id);
+               $readonly = false;
+               if (count($layoutExtraFieldIDs) > 0) {
+                       $mandatoryDisplay = false;
+                       $return .= $HTML->listTableTop();
+                       $selected = array();
+                       $i = 0;
+                       if (is_object($ah)) {
+                               $selected = $ah->getExtraFieldData();
+                       } elseif ($func = 'add') {
+                               $selected = $ath->getExtraFieldsDefaultValue();
+                       }
+                       if (!forge_check_perm('tracker', $atid, 'submit')) {
+                               $readonly = true;
+                       }
+                       $maxcol = 0;
+                       foreach ($layoutExtraFieldIDs as $row_id => $column_id) 
{
+                               $numcol = 1;
+                               $cells = array();
+                               foreach ($column_id as $key => $extrafieldIDs) {
+                                       if ($key != $numcol) {
+                                               $cells[][] = '&nbsp;';
+                                       }
+                                       foreach ($extrafieldIDs as 
$extrafieldID) {
+                                               $extrafieldObject = new 
ArtifactExtraField($ath, $extrafieldID);
+                                               if ($func == 'add') {
+                                                       $display = 
!(int)$extrafieldObject->isHiddenOnSubmit();
+                                               } else {
+                                                       $display = true;
+                                               }
+                                               if ($display) {
+                                                       $value = null;
+                                                       $allowed = false;
+                                                       if 
(isset($selected[$extrafieldID])) {
+                                                               $value = 
$selected[$extrafieldID];
+                                                       } elseif 
(isset($extra_fields[$extrafieldID])) {
+                                                               $value = 
$extra_fields[$extrafieldID];
+                                                       }
+                                                       $attrs = array();
+                                                       $mandatory = '';
+                                                       if 
($extrafieldObject->isRequired() && !$readonly) {
+                                                               $mandatory = 
utils_requiredField();
+                                                               
$mandatoryDisplay = true;
+                                                               
$attrs['required'] = 'required';
+                                                       }
+                                                       if 
(strlen($extrafieldObject->getDescription()) > 0) {
+                                                               $attrs['title'] 
= $extrafieldObject->getDescription();
+                                                       }
+                                                       $cellContent = 
html_e('strong', array(), 
$extrafieldObject->getName()._(':')).$mandatory.html_e('br');
+                                                       switch 
($extrafieldObject->getType()) {
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_SELECT:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = $extrafieldObject->getShow100label();
+                                                                               
} else {
+                                                                               
        $value = $ath->getElementName($value);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$parent = $extrafieldObject->getParent();
+                                                                               
if (!is_null($parent) && !empty($parent) && $parent != '100') {
+                                                                               
        $selectedElmnts = (isset($selected[$parent]) ? $selected[$parent] : '');
+                                                                               
        $allowed = $aef->getAllowedValues($selectedElmnts);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$ath->renderSelect($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), false, 
false, $allowed, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_CHECKBOX:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = $extrafieldObject->getShow100label();
+                                                                               
} else {
+                                                                               
        $value = explode(',', $ath->getElementName($value));
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.join(html_e('br'), $value), 'style' => 
'vertical-align: top;');
+                                                                       } else {
+                                                                               
$parent = $extrafieldObject->getParent();
+                                                                               
if (!is_null($parent) && !empty($parent) && $parent != '100') {
+                                                                               
        $selectedElmnts = (isset($selected[$parent]) ? $selected[$parent] : '');
+                                                                               
        $allowed = $aef->getAllowedValues($selectedElmnts);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$ath->renderCheckbox($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), 
$allowed, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_RADIO:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = $extrafieldObject->getShow100label();
+                                                                               
} else {
+                                                                               
        $value = $ath->getElementName($value);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$parent = $extrafieldObject->getParent();
+                                                                               
if (!is_null($parent) && !empty($parent) && $parent != '100') {
+                                                                               
        $selectedElmnts = (isset($selected[$parent]) ? $selected[$parent] : '');
+                                                                               
        $allowed = $aef->getAllowedValues($selectedElmnts);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$ath->renderRadio($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), false, 
false, $allowed, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_TEXT:
+                                                                       if 
($readonly) {
+                                                                               
if (strlen($value) > 0) {
+                                                                               
        $value = preg_replace('/((http|https|ftp):\/\/\S+)/', "<a href=\"\\1\" 
target=\"_blank\">\\1</a>", $value);
+                                                                               
} else {
+                                                                               
        $value = '&nbsp;';
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$attrs['style'] = 'box-sizing: border-box; width: 100%';
+                                                                               
if ($extrafieldObject->getPattern()) {
+                                                                               
        $attrs['pattern'] = $extrafieldObject->getPattern();
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$ath->renderTextField($extrafieldID, $value, 
$extrafieldObject->getAttribute1(), $extrafieldObject->getAttribute2(), 
$attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_MULTISELECT:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = $extrafieldObject->getShow100label();
+                                                                               
} else {
+                                                                               
        $value = explode(',', $ath->getElementName($value));
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.join(html_e('br'), $value), 'style' => 
'vertical-align: top;');
+                                                                       } else {
+                                                                               
$parent = $extrafieldObject->getParent();
+                                                                               
if (!is_null($parent) && !empty($parent) && $parent != '100') {
+                                                                               
        $selectedElmnts = (isset($selected[$parent]) ? $selected[$parent] : '');
+                                                                               
        $allowed = $aef->getAllowedValues($selectedElmnts);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$ath->renderMultiSelectBox($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), 
$allowed, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_TEXTAREA:
+                                                                       if 
($readonly) {
+                                                                               
if (strlen($value) > 0) {
+                                                                               
        $value = preg_replace('/((http|https|ftp):\/\/\S+)/', "<a href=\"\\1\" 
target=\"_blank\">\\1</a>", $value);
+                                                                               
} else {
+                                                                               
        $value = '&nbsp;';
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$attrs['style'] = 'box-sizing: border-box; width: 100%';
+                                                                               
$cells[] = array($cellContent.$ath->renderTextArea($extrafieldID, $value, 
$extrafieldObject->getAttribute1(), $extrafieldObject->getAttribute2(), 
$attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_STATUS:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = $extrafieldObject->getShow100label();
+                                                                               
} else {
+                                                                               
        $value = $ath->getElementName($value);
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$atw = new ArtifactWorkflow($ath, $extrafieldID);
+                                                                               
// Special treatment for the initial step (Submit). In this case, the initial 
value is the first value.
+                                                                               
if (!$value) {
+                                                                               
        $value = 100;
+                                                                               
}
+                                                                               
$allowed = $atw->getNextNodes($value);
+                                                                               
$allowed[] = $value;
+                                                                               
$cells[] = array($cellContent.$ath->renderSelect($extrafieldID, $value, false, 
$extrafieldObject->getShow100label(), false, false, $allowed, $attrs), 'style' 
=> 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               //case 
ARTIFACT_EXTRAFIELDTYPE_ASSIGNEE:
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_RELATION:
+                                                                       if 
($readonly) {
+                                                                               
$value = preg_replace_callback('/\b(\d+)\b/', create_function('$matches', 
'return _artifactid2url($matches[1], \'title\');'), $value);
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
// specific rewrite of cellContent
+                                                                               
$cellContent = '<div style="width:100%; line-height: 20px;">' .
+                                                                               
                '<div style="float:left;">'.html_e('strong', array(), 
$extrafieldObject->getName()._(':')).$mandatory.'</div>' .
+                                                                               
                '<div>' . $HTML->getEditFilePic(_('Click to edit'), _('Click to 
edit'), array('class' => 'mini_buttons tip-ne', 'onclick'=>"switch2edit(this, 
'show$extrafieldID', 'edit$extrafieldID')")) . '</div>' .
+                                                                               
                '</div>';
+                                                                               
$cells[] = array($cellContent.$ath->renderRelationField($extrafieldID, $value, 
$extrafieldObject->getAttribute1(), $extrafieldObject->getAttribute2(), 
$attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_INTEGER:
+                                                                       if 
($readonly) {
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$cells[] = array($cellContent.$ath->renderIntegerField($extrafieldID, $value, 
$extrafieldObject->getAttribute1(), $extrafieldObject->getAttribute2(), 
$attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               /* reserved for 
aljeux extension, for merge into FusionForge */
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_FORMULA:
+                                                                       break;
+                                                               /* reserved for 
Evolvis extension, for merge into FusionForge */
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_DATETIME:
+                                                                       if 
($readonly) {
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$cells[] = array($cellContent.$ath->renderDatetime($extrafieldID, $value, 
$attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               /* 12: reserved 
DATETIME*/
+                                                               /* 13: reserved 
SLA */
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_SLA:
+                                                                       break;
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_USER:
+                                                                       if 
($readonly) {
+                                                                               
if ($value == 100) {
+                                                                               
        $value = _('None');
+                                                                               
} else {
+                                                                               
        $user = user_get_object($value);
+                                                                               
        $value = $user->getRealName().' ('.html_e('samp', array(), 
util_make_link_u($user->getUnixname(),$value,$user->getUnixname())).')';
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$cells[] = array($cellContent.$ath->renderUserField($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), false, 
false, false, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                               /* 15: reserved 
MULTIUSER */
+                                                               case 
ARTIFACT_EXTRAFIELDTYPE_RELEASE:
+                                                                       if 
($readonly) {
+                                                                               
if ($value != 0) {
+                                                                               
        $releaseObj = frsrelease_get_object($value);
+                                                                               
        $value = $releaseObj->FRSPackage->getName().' - 
'.$releaseObj->getName();
+                                                                               
}
+                                                                               
$cells[] = array($cellContent.$value, 'style' => 'vertical-align: top;');
+                                                                       } else {
+                                                                               
$cells[] = array($cellContent.$ath->renderReleaseField($extrafieldID, $value, 
$extrafieldObject->getShow100(), $extrafieldObject->getShow100label(), false, 
false, false, $attrs), 'style' => 'vertical-align: top;');
+                                                                       }
+                                                                       break;
+                                                       }
+                                               }
+                                       }
+                                       $numcol++;
+                                       if ($numcol > $maxcol) {
+                                               $maxcol = $numcol;
+                                       }
+                               }
+                               while (count($cells) < ($maxcol -1)) {
+                                       $cells[][] = '&nbsp;';
+                               }
+                               $return .= $HTML->multiTableRow(array('class' 
=> $HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       }
+                       $return .= $HTML->listTableBottom();
+                       $return .= $ath->javascript();
+                       $return .= init_datetimepicker();
+                       if ($mandatoryDisplay) {
+                               $return .= $HTML->addRequiredFieldsInfoBox();
+                       }
+               }
+               if (!$readonly) {
+                       $return .= html_e('p', array('class' => 'middleRight'), 
html_e('input', array('type' => 'submit', 'name' => 'submit', 'value' => 
_('Save Changes'), 'title' => _('Save is validating the complete form'))));
+               }
+               return $return;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+}
diff --git a/src/common/widget/Widget_TrackerDefaultActions.class.php 
b/src/common/widget/Widget_TrackerDefaultActions.class.php
new file mode 100644
index 0000000..147a563
--- /dev/null
+++ b/src/common/widget/Widget_TrackerDefaultActions.class.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Default Action Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+
+class Widget_TrackerDefaultActions extends Widget {
+
+       var $content;
+
+       function __construct() {
+               global $func;
+               $request =& HTTPRequest::instance();
+               $owner_id   = (int)substr($request->get('owner'), 1);
+               if (!$owner_id) {
+                       $owner_id = $request->get('atid');
+               }
+               if (forge_check_perm('tracker', $owner_id, 'tech') && ($func == 
'detail')) {
+                       parent::__construct('trackerdefaultactions', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+                       $this->content['title'] = _('Actions');
+               }
+       }
+
+       function getTitle() {
+               return $this->content['title'];
+       }
+
+       function getDescription() {
+               return _('Default actions widget for monitor, votes & delete.');
+       }
+
+       function isAvailable() {
+               return isset($this->content['title']);
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               $return = $HTML->listTableTop();
+               $cells = array();
+               if ($ah->isMonitoring()) {
+                       $img="xmail16w.png";
+                       $text=_('Stop monitoring');
+               } else {
+                       $img="mail16w.png";
+                       $text=_('Monitor');
+               }
+               $i = 0;
+               $cells[][] = 
util_make_link('/tracker/?group_id='.$group_id.'&artifact_id='.$ah->getID().'&atid='.$ath->getID().'&func=monitor',
 html_e('strong', array(), html_image('ic/'.$img, 20, 20).' '.$text), 
array('id' => 'tracker-monitor', 'title' => 
util_html_secure(html_get_tooltip_description('monitor'))));
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               $votes = $ah->getVotes();
+               if ($votes[1]) {
+                       $cells = array();
+                       $cellContent = html_e('span', array('id' => 
'tracker-votes', 'title' => html_get_tooltip_description('votes')), 
html_e('strong', array(), _('Votes') . _(': ')).sprintf('%1$d/%2$d (%3$d%%)', 
$votes[0], $votes[1], $votes[2]));
+                       if ($ath->canVote()) {
+                               if ($ah->hasVote()) {
+                                       $key = 'pointer_down';
+                                       $txt = _('Retract Vote');
+                               } else {
+                                       $key = 'pointer_up';
+                                       $txt = _('Cast Vote');
+                               }
+                               $cellContent .= 
util_make_link('/tracker/?group_id='.$group_id.'&aid='.$ah->getID().'&atid='.$ath->getID().'&func='.$key,
 html_image('ic/'.$key.'.png', 16, 16), array('id' => 'tracker-vote', 'alt' => 
$txt, 'title' => util_html_secure(html_get_tooltip_description('vote'))));
+                       }
+                       $cells[][] = $cellContent;
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               }
+               if (forge_check_perm('tracker', $atid, 'manager')) {
+                       $cells = array();
+                       $cells[][] = 
util_make_link('/tracker/?func=deleteartifact&aid='.$aid.'&group_id='.$group_id.'&atid='.$atid,
 $HTML->getDeletePic().html_e('strong', array(), _('Delete')));
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               }
+               $return .= $HTML->listTableBottom();
+               return $return;
+       }
+
+       function canBeRemove() {
+               return false;
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+}
diff --git a/src/common/widget/Widget_TrackerGeneral.class.php 
b/src/common/widget/Widget_TrackerGeneral.class.php
new file mode 100644
index 0000000..41b0aca
--- /dev/null
+++ b/src/common/widget/Widget_TrackerGeneral.class.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * General Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+
+class Widget_TrackerGeneral extends Widget {
+
+       var $content;
+
+       function __construct() {
+               $request =& HTTPRequest::instance();
+               $owner_id = (int)substr($request->get('owner'), 1);
+               if (!$owner_id) {
+                       $owner_id = (int)$request->get('atid');
+               }
+               parent::__construct('trackergeneral', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+               $this->content['title'] = _('General Information');
+       }
+
+       function getTitle() {
+               return $this->content['title'];
+       }
+
+       function getDescription() {
+               return _('Default widget where general informations are stored 
& displayed. Open/Modified/Close dates, submitted By, last Modified by.');
+       }
+
+       function isAvailable() {
+               return isset($this->content['title']);
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               global $func;
+
+               if ($func == 'add') {
+                       $return = html_e('p', array(), _('Submit Instruction'));
+                       $renderSubmitInstructions = 
$ath->renderSubmitInstructions();
+                       if (strlen($renderSubmitInstructions) > 0) {
+                               $return .= $renderSubmitInstructions;
+                       } else {
+                               $return .= $HTML->information('No specific 
instruction');
+                       }
+               } elseif ($func == 'detail') {
+                       $i = 0;
+                       $return = $HTML->listTableTop();
+                       $cells = array();
+                       $cells[][] = html_e('strong', array(), _('Submitted 
by')._(':'));
+                       $cellContent = $ah->getSubmittedRealName();
+                       if($ah->getSubmittedBy() != 100) {
+                               $unixName = $ah->getSubmittedUnixName();
+                               $by = $ah->getSubmittedBy();
+                               $cellContent .= ' ('.html_e('samp', array(), 
util_make_link_u($unixName, $by, $unixName)).')';
+                       }
+                       $cells[][] = $cellContent;
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       $cells = array();
+                       $cells[][] = html_e('strong', array(), _('Date 
Submitted')._(':'));
+                       $cells[][] = date(_('Y-m-d H:i'), $ah->getOpenDate());
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       $cells = array();
+                       $cells[][] = html_e('strong', array(), _('Last Modified 
by')._(':'));
+                       $cellContent = $ah->getLastModifiedRealName();
+                       if($ah->getLastModifiedBy() != 100) {
+                               $unixName = $ah->getLastModifiedUnixName();
+                               $by = $ah->getLastModifiedBy();
+                               $cellContent .= ' ('.html_e('samp', array(), 
util_make_link_u($unixName, $by, $unixName)).')';
+                       }
+                       $cells[][] = $cellContent;
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       $cells = array();
+                       $cells[][] = html_e('strong', array(), _('Last 
Modified')._(':'));
+                       $cells[][] = date(_('Y-m-d H:i'), 
$ah->getLastModifiedDate());
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       $close_date = $ah->getCloseDate();
+                       if ($ah->getStatusID()==2 && $close_date > 1) {
+                               $cells = array();
+                               $cells[][] = html_e('strong', array(), _('Date 
Closed')._(':'));
+                               $cells[][] = date(_('Y-m-d H:i'), $close_date);
+                               $return .= $HTML->multiTableRow(array('class' 
=> $HTML->boxGetAltRowStyle($i++, true)), $cells);
+                       }
+                       $return .= $HTML->listTableBottom();
+               }
+               return $return;
+       }
+
+       function canBeRemove() {
+               return false;
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+}
diff --git a/src/common/widget/Widget_TrackerMain.class.php 
b/src/common/widget/Widget_TrackerMain.class.php
new file mode 100644
index 0000000..a539984
--- /dev/null
+++ b/src/common/widget/Widget_TrackerMain.class.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Main Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+
+class Widget_TrackerMain extends Widget {
+
+       var $content;
+
+       function __construct() {
+               $request =& HTTPRequest::instance();
+               $owner_id   = (int)substr($request->get('owner'), 1);
+               parent::__construct('trackermain', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+               $this->content['title'] = _('Internal Fields');
+       }
+
+       function getTitle() {
+               return $this->content['title'];
+       }
+
+       function getDescription() {
+               return _('Default widget where default fields are stored & 
displayed. Priority, Data Types, ...');
+       }
+
+       function isAvailable() {
+               return isset($this->content['title']);
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               global $func;
+
+               //manage redirect in case of missing required fields
+               global $assigned_to;
+               global $priority;
+
+               $return = $HTML->listTableTop();
+               $i = 0;
+               $atf = new ArtifactTypeFactory ($group);
+               $cells = array();
+               if (forge_check_perm('tracker', $atid, 'manager') && ($func == 
'detail')) {
+                       $tids = array();
+                       foreach ($atf->getArtifactTypes() as $at) {
+                               if (forge_check_perm ('tracker', $at->getID(), 
'manager')) {
+                                       $tids[] = $at->getID();
+                               }
+                       }
+
+                       $res = db_query_params('SELECT group_artifact_id, name
+                                               FROM artifact_group_list
+                                               WHERE group_artifact_id = ANY 
($1)',
+                                               array 
(db_int_array_to_any_clause($tids)));
+
+                       $cells[][] = html_e('strong', array(), _('Data 
Type')._(': '));
+                       $cells[][] = html_build_select_box($res, 
'new_artifact_type_id', $ath->getID(), false);
+               } else {
+                       $cells[][] = html_e('strong', array(), _('Data 
Type')._(': '));
+                       $cells[][] = $ath->getName();
+               }
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               $cells = array();
+               $cells[][] = html_e('strong', array(), _('Assigned to')._(': 
'));
+               if (forge_check_perm('tracker', $atid, 'manager')) {
+                       if ($func == 'detail') {
+                               $cells[][] = $ath->technicianBox('assigned_to', 
$ah->getAssignedTo());
+                       } else {
+                               $cells[][] = $ath->technicianBox('assigned_to', 
$assigned_to);
+                       }
+               } else {
+                       $cells[][] = $ah->getAssignedRealName().' 
('.$ah->getAssignedUnixName().')';
+               }
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               if (!$ath->usesCustomStatuses()) {
+                       $cells = array();
+                       $cells[][] = html_e('strong', array(), _('State')._(': 
'));
+                       if (forge_check_perm('tracker', $atid, 'tech')) {
+                               if ($func == 'detail') {
+                                       $cells[][] = 
$ath->statusBox('status_id', $ah->getStatusID());
+                               } else {
+                                       $cells[][] = 
$ath->statusBox('status_id');
+                               }
+                       } else {
+                               $cells[][] = $ah->getStatusName();
+                       }
+                       $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               }
+               $cells = array();
+               $cells[][] = html_e('strong', array(), _('Priority')._(': '));
+               if (forge_check_perm('tracker', $atid, 'manager')) {
+                       if ($func == 'detail') {
+                               $cells[][] = 
build_priority_select_box('priority', $ah->getPriority());
+                       } else {
+                               $cells[][] = 
build_priority_select_box('priority', $priority);
+                       }
+               } else {
+                       $cells[][] = $ah->getPriority();
+               }
+               $return .= $HTML->multiTableRow(array('class' => 
$HTML->boxGetAltRowStyle($i++, true)), $cells);
+               $return .= $HTML->listTableBottom();
+               if (forge_check_perm('tracker', $atid, 'tech')) {
+                       $return .= html_e('p', array('class' => 'middleRight'), 
html_e('input', array('type' => 'submit', 'name' => 'submit', 'value' => 
_('Save Changes'), 'title' => _('Save is validating the complete form'))));
+               }
+               return $return;
+       }
+
+       function canBeRemove() {
+               return false;
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+}
diff --git a/src/common/widget/Widget_TrackerSummary.class.php 
b/src/common/widget/Widget_TrackerSummary.class.php
new file mode 100644
index 0000000..3e07d55
--- /dev/null
+++ b/src/common/widget/Widget_TrackerSummary.class.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Summary Tracker Content Widget Class
+ *
+ * Copyright 2016, Franck Villaume - TrivialDev
+ * http://fusionforge.org
+ *
+ * This file is a part of Fusionforge.
+ *
+ * Fusionforge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fusionforge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Fusionforge. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'Widget.class.php';
+require_once $gfwww.'include/note.php';
+
+class Widget_TrackerSummary extends Widget {
+
+       var $content;
+
+       function __construct() {
+               $request =& HTTPRequest::instance();
+               $owner_id   = (int)substr($request->get('owner'), 1);
+               parent::__construct('trackersummary', $owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER);
+               $this->content['title'] = _('Description');
+       }
+
+       function getTitle() {
+               return $this->content['title'];
+       }
+
+       function getDescription() {
+               return _("Default widget where summary & description fields are 
stored & displayed.");
+       }
+
+       function isAvailable() {
+               return isset($this->content['title']);
+       }
+
+       function getContent() {
+               global $ath;
+               global $ah;
+               global $group_id;
+               global $group;
+               global $aid;
+               global $atid;
+               global $HTML;
+               global $func;
+
+               //manage redirect in case of missing required fields
+               global $summary;
+               global $details;
+
+               $return = '';
+               $inputAttrs = array('type' => 'text', 'name' => 'summary', 
'style' => 'width:99%', 'value' => $summary);
+               if ($func == 'detail') {
+                       $inputAttrs['value'] = $ah->getSummary();
+               }
+               if (!forge_check_perm('tracker', $atid, 'submit')) {
+                       $inputAttrs['disabled'] = 'disabled';
+                       $return .= html_e('input', array('type' => 'hidden', 
'name' => 'summary', 'value' => $ah->getSummary()));
+                       $requiredInfo = '';
+               } else {
+                       $inputAttrs['required'] = 'required';
+                       $requiredInfo = utils_requiredField();
+               }
+               $return .= html_e('p', array(), _('Summary')._(': 
').$requiredInfo.html_e('input', $inputAttrs));
+               if ($func == 'detail') {
+                       if (forge_check_perm('tracker', $atid, 'tech')) {
+                               $editable = true;
+                       } else {
+                               $editable = false;
+                       }
+                       $return .= $ah->showDetails($editable);
+               } elseif ($func == 'add') {
+                       $return .= notepad_func();
+                       $return .= $HTML->listTableTop();
+                       $content = html_e('strong', array(), _('Detailed 
description').$requiredInfo._(':'));
+                       $content .= 
notepad_button('document.forms.trackerform.details');
+                       $content .= html_e('textarea', 
array('id'=>'tracker-description', 'required'=>'required', 'name'=>'details', 
'rows'=>'20', 'style'=>'box-sizing: border-box; width: 100%', 
'title'=>util_html_secure(html_get_tooltip_description('description'))), 
$details, false);
+                       $cells = array();
+                       $cells[][] = $content;
+                       $return .= $HTML->multiTableRow(array(), $cells);
+                       $return .= $HTML->listTableBottom();
+
+               }
+               if (forge_check_perm('tracker', $atid, 'submit')) {
+                       $return .= $HTML->addRequiredFieldsInfoBox();
+                       $return .= html_e('p', array('class' => 'middleRight'), 
html_e('input', array('type' => 'submit', 'name' => 'submit', 'value' => 
_('Save Changes'), 'title' => _('Save is validating the complete form'))));
+               }
+               return $return;
+       }
+
+       function canBeRemove() {
+               return false;
+       }
+
+       function canBeMinize() {
+               return false;
+       }
+
+       function getCategory() {
+               return _('Trackers');
+       }
+}
diff --git a/src/db/20161113-widget-artifact-display.sql 
b/src/db/20161113-widget-artifact-display.sql
new file mode 100644
index 0000000..396c7f0
--- /dev/null
+++ b/src/db/20161113-widget-artifact-display.sql
@@ -0,0 +1,20 @@
+CREATE SEQUENCE artifact_display_widget_pk_seq
+    START WITH 1
+    INCREMENT BY 1
+    MAXVALUE 2147483647
+    NO MINVALUE
+    CACHE 1;
+
+CREATE TABLE artifact_display_widget (
+    id       integer DEFAULT nextval('artifact_display_widget_pk_seq'::text) 
NOT NULL,
+    owner_id integer NOT NULL,
+    title    text    NOT NULL,
+    cols     integer NOT NULL default 1
+);
+
+CREATE TABLE artifact_display_widget_field (
+    id        integer NOT NULL,
+    field_id  integer NOT NULL,
+    column_id integer NOT NULL default 1,
+    row_id    integer NOT NULL default 1
+);
diff --git a/src/etc/config.ini.d/defaults.ini 
b/src/etc/config.ini.d/defaults.ini
index 11f44b0..8710393 100644
--- a/src/etc/config.ini.d/defaults.ini
+++ b/src/etc/config.ini.d/defaults.ini
@@ -94,6 +94,7 @@ use_home = yes
 use_my = yes
 check_password_strength = no
 use_object_associations = yes
+use_tracker_widget_display = no
 
 scm_single_host = yes
 system_user=fusionforge
diff --git a/src/www/include/Layout.class.php b/src/www/include/Layout.class.php
index 99db4ae..76b75f1 100644
--- a/src/www/include/Layout.class.php
+++ b/src/www/include/Layout.class.php
@@ -1375,22 +1375,22 @@ if (isset($params['group']) && $params['group']) {
                echo html_ao('div', array('class' => 'widget_titlebar '. 
($readonly?'':'widget_titlebar_handle')));
                echo html_e('div', array('class' => 'widget_titlebar_title'), 
$widget->getTitle(), false);
                if (!$readonly) {
-                       echo html_ao('div', array('class' => 
'widget_titlebar_close'));
-                       echo 
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=widget&name['.$widget->id.'][remove]='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto('ic/close.png', _('Close'), _('Close')));
-                       echo html_ac(html_ap() -1);
-                       if ($is_minimized) {
-                               echo html_ao('div', array('class' => 
'widget_titlebar_maximize'));
-                               echo 
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=maximize&name['.$widget->id.']='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto($this->_getTogglePlusForWidgets(), _('Maximize'), 
_('Maximize')));
-                               echo html_ac(html_ap() -1);
-                       } else {
-                               echo html_ao('div', array('class' => 
'widget_titlebar_minimize'));
-                               echo 
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=minimize&name['.$widget->id.']='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto($this->_getToggleMinusForWidgets(), _('Minimize'), 
_('Minimize')));
-                               echo html_ac(html_ap() -1);
+                       if ($widget->canBeRemove()) {
+                               echo html_e('div', array('class' => 
'widget_titlebar_close'),
+                                       
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=widget&name['.$widget->id.'][remove]='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto('ic/close.png', _('Close'), _('Close'))));
+                       }
+                       if ($widget->canBeMinize()) {
+                               if ($is_minimized) {
+                                       echo html_e('div', array('class' => 
'widget_titlebar_maximize'),
+                                               
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=maximize&name['.$widget->id.']='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto($this->_getTogglePlusForWidgets(), _('Maximize'), 
_('Maximize'))));
+                               } else {
+                                       echo html_e('div', array('class' => 
'widget_titlebar_minimize'),
+                                               
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=minimize&name['.$widget->id.']='.$widget->getInstanceId().'&column_id='.$column_id.'&layout_id='.$layout_id,
 $this->getPicto($this->_getToggleMinusForWidgets(), _('Minimize'), 
_('Minimize'))));
+                               }
                        }
                        if (strlen($widget->hasPreferences())) {
-                               echo html_ao('div', array('class' => 
'widget_titlebar_prefs'));
-                               echo 
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=preferences&name['.$widget->id.']='.$widget->getInstanceId().'&layout_id='.$layout_id,
 _('Preferences'));
-                               echo html_ac(html_ap() -1);
+                               echo html_e('div', array('class' => 
'widget_titlebar_prefs'),
+                                       
util_make_link('/widgets/updatelayout.php?owner='.$owner_type.$owner_id.'&action=preferences&name['.$widget->id.']='.$widget->getInstanceId().'&layout_id='.$layout_id,
 _('Preferences')));
                        }
                }
                if ($widget->hasRss()) {
diff --git a/src/www/include/jquery_plugins.php 
b/src/www/include/jquery_plugins.php
index 0dcd692..2f127d3 100644
--- a/src/www/include/jquery_plugins.php
+++ b/src/www/include/jquery_plugins.php
@@ -1,28 +1,28 @@
 <?php
 /**
  * jQuery plugins toolbox
-*
-* Copyright 2016 Stéphane-Eymeric Bredthauer - TrivialDev
-* http://fusionforge.org/
-*
-* This file is part of FusionForge. FusionForge is free software;
-* you can redistribute it and/or modify it under the terms of the
-* GNU General Public License as published by the Free Software
-* Foundation; either version 2 of the Licence, or (at your option)
-* any later version.
-*
-* FusionForge is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with FusionForge; if not, write to the Free Software Foundation, Inc.,
-* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
+ *
+ * Copyright 2016 Stéphane-Eymeric Bredthauer - TrivialDev
+ * http://fusionforge.org/
+ *
+ * This file is part of FusionForge. FusionForge is free software;
+ * you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or (at your option)
+ * any later version.
+ *
+ * FusionForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FusionForge; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
 
 function init_datetimepicker() {
-       
+
        // awful hack
        $language_code = 
language_name_to_locale_code(choose_language_from_context ());
        if (!in_array($language_code,array('en-GB','pt-BR','sr-YU','zh-TW'))) {
@@ -30,4 +30,4 @@ function init_datetimepicker() {
        }
        $javascript = "$.datetimepicker.setLocale('".$language_code."'); 
$('.datetimepicker').datetimepicker();";
        return html_e('script', array( 'type'=>'text/javascript'), 
'//<![CDATA['."\n".'$(function(){'.$javascript.'});'."\n".'//]]>');
-}
\ No newline at end of file
+}
diff --git a/src/www/widgets/updatelayout.php b/src/www/widgets/updatelayout.php
index 6362dfe..65d67b1 100644
--- a/src/www/widgets/updatelayout.php
+++ b/src/www/widgets/updatelayout.php
@@ -34,6 +34,8 @@ $good = false;
 $redirect   = '/';
 $owner = $request->get('owner');
 
+error_log($owner);
+
 if ($owner) {
        $owner_id   = (int)substr($owner, 1);
        $owner_type = substr($owner, 0, 1);
@@ -65,6 +67,17 @@ if ($owner) {
                        }
                        $good = true;
                        break;
+               case WidgetLayoutManager::OWNER_TYPE_TRACKER:
+                       if ($at = artifactType_get_object($owner_id)) {
+                               $_REQUEST['group_id'] = $_GET['group_id'] = 
$at->Group->getID();
+                               $request->params['group_id'] = 
$at->Group->getID(); //bad!
+                               $redirect = 
'/tracker/?group_id='.$at->Group->getID().'&atid='.$at->getID();
+                               if (!forge_check_global_perm('forge_admin') && 
!forge_check_perm('tracker_admin', $at->getID())) {
+                                       
$GLOBALS['Response']->redirect($redirect);
+                               }
+                               $good = true;
+                       }
+                       break;
                default:
                        break;
        }
@@ -74,7 +87,6 @@ if ($owner) {
                        if ($request->exist('name')) {
                                $param = $request->get('name');
                                $name = array_pop(array_keys($param));
-                               $instance_id = (int)$param[$name];
                        }
                        switch($request->get('action')) {
                                case 'widget':
@@ -85,14 +97,13 @@ if ($owner) {
                                                                switch($action) 
{
                                                                        case 
'remove':
                                                                                
$instance_id = (int)$param[$name][$action];
-                                                                               
if ($owner_type == WidgetLayoutManager::OWNER_TYPE_GROUP) {
-                                                                               
        if (forge_check_perm ('project_admin', $owner_id, NULL)) {
+                                                                               
if (($owner_type == WidgetLayoutManager::OWNER_TYPE_GROUP) && (forge_check_perm 
('project_admin', $owner_id, NULL))) {
+                                                                               
                $lm->removeWidget($owner_id, $owner_type, $layout_id, $name, 
$instance_id, $widget);
+                                                                               
} elseif (($owner_type == WidgetLayoutManager::OWNER_TYPE_HOME) && 
(forge_check_global_perm('forge_admin'))) {
                                                                                
                $lm->removeWidget($owner_id, $owner_type, $layout_id, $name, 
$instance_id, $widget);
-                                                                               
        }
-                                                                               
} elseif ($owner_type == WidgetLayoutManager::OWNER_TYPE_HOME) {
-                                                                               
        if (forge_check_global_perm('forge_admin')) {
+                                                                               
} elseif (($owner_type == WidgetLayoutManager::OWNER_TYPE_TRACKER) && 
(forge_check_perm('tracker_admin', $owner_id))) {
+                                                                               
                error_log('ici');
                                                                                
                $lm->removeWidget($owner_id, $owner_type, $layout_id, $name, 
$instance_id, $widget);
-                                                                               
        }
                                                                                
} else {
                                                                                
        $lm->removeWidget($owner_id, $owner_type, $layout_id, $name, 
$instance_id, $widget);
                                                                                
}
diff --git a/src/www/widgets/widgets.php b/src/www/widgets/widgets.php
index 63865c4..5731f0c 100644
--- a/src/www/widgets/widgets.php
+++ b/src/www/widgets/widgets.php
@@ -90,6 +90,22 @@ if (session_loggedin()) {
                                                
$GLOBALS['Response']->redirect('/');
                                        }
                                        break;
+                               case WidgetLayoutManager::OWNER_TYPE_TRACKER:
+                                       if ($at = 
artifactType_get_object($owner_id)) {
+
+                                               $_REQUEST['group_id'] = 
$_GET['group_id'] = $at->Group->getID();
+                                               $request->params['group_id'] = 
$at->Group->getID(); //bad!
+                                               $redirect = 
'/tracker/?group_id='. $at->Group->getID();
+                                               if 
(forge_check_global_perm('forge_admin') || forge_check_perm('tracker_admin', 
$at->getID())) {
+                                                       $ath = new 
ArtifactTypeHtml($at->Group, $at->getID());
+                                                       
$ath->header(array('atid'=>$ath->getID(), 'title'=>$ath->getName()));
+                                                       
$lm->displayAvailableWidgets($owner_id, 
WidgetLayoutManager::OWNER_TYPE_TRACKER, $layout_id);
+                                                       $ath->footer();
+                                               } else {
+                                                       
$GLOBALS['Response']->redirect($redirect);
+                                               }
+                                       }
+                                       break;
                                default:
                                        break;
                        }

-----------------------------------------------------------------------

Summary of changes:
 src/common/tracker/Artifact.class.php              |   8 +
 src/common/tracker/ArtifactExtraField.class.php    |   2 +-
 src/common/tracker/ArtifactFactory.class.php       |   2 +-
 src/common/tracker/ArtifactType.class.php          |   4 +-
 src/common/tracker/actions/ajax.php                |   2 +
 src/common/tracker/actions/browse.php              |   2 +-
 src/common/tracker/actions/detail.php              |  25 +-
 src/common/tracker/actions/mod-limited.php         |  27 +-
 src/common/tracker/actions/mod.php                 |  25 +-
 src/common/tracker/actions/tracker.php             |  27 +-
 .../tracker/actions/widget_artifact_display.php    |  83 ++++
 src/common/tracker/include/ArtifactHtml.class.php  | 155 ++++----
 .../tracker/include/ArtifactTypeHtml.class.php     |  61 ++-
 src/common/tracker/views/form-addextrafield.php    |  10 +-
 src/common/widget/Widget.class.php                 |  38 +-
 src/common/widget/WidgetLayoutManager.class.php    |  95 ++++-
 src/common/widget/Widget_TrackerComment.class.php  | 185 +++++++++
 src/common/widget/Widget_TrackerContent.class.php  | 438 +++++++++++++++++++++
 .../widget/Widget_TrackerDefaultActions.class.php  | 112 ++++++
 src/common/widget/Widget_TrackerGeneral.class.php  | 124 ++++++
 src/common/widget/Widget_TrackerMain.class.php     | 143 +++++++
 src/common/widget/Widget_TrackerSummary.class.php  | 115 ++++++
 src/db/20161113-widget-artifact-display.sql        |  20 +
 src/etc/config.ini.d/defaults.ini                  |   1 +
 src/www/include/Layout.class.php                   |  28 +-
 src/www/include/jquery_plugins.php                 |  42 +-
 src/www/widgets/updatelayout.php                   |  25 +-
 src/www/widgets/widgets.php                        |  16 +
 28 files changed, 1592 insertions(+), 223 deletions(-)
 create mode 100644 src/common/tracker/actions/widget_artifact_display.php
 create mode 100644 src/common/widget/Widget_TrackerComment.class.php
 create mode 100644 src/common/widget/Widget_TrackerContent.class.php
 create mode 100644 src/common/widget/Widget_TrackerDefaultActions.class.php
 create mode 100644 src/common/widget/Widget_TrackerGeneral.class.php
 create mode 100644 src/common/widget/Widget_TrackerMain.class.php
 create mode 100644 src/common/widget/Widget_TrackerSummary.class.php
 create mode 100644 src/db/20161113-widget-artifact-display.sql


hooks/post-receive
-- 
FusionForge

_______________________________________________
Fusionforge-commits mailing list
[email protected]
http://lists.fusionforge.org/cgi-bin/mailman/listinfo/fusionforge-commits

Reply via email to