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  97ffe89726b1a95bfa03d60a4805fb54d821da14 (commit)
      from  5c02d437ae2ab9d01370cc9aec4ecc46f3602746 (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=97ffe89726b1a95bfa03d60a4805fb54d821da14

commit 97ffe89726b1a95bfa03d60a4805fb54d821da14
Author: Stéphane-Eymeric Bredthauer <[email protected]>
Date:   Thu May 4 13:28:49 2017 +0200

    Tracker: Artifacts dependencies, part 1

diff --git a/src/common/tracker/Artifact.class.php 
b/src/common/tracker/Artifact.class.php
index c957df7..b669579 100644
--- a/src/common/tracker/Artifact.class.php
+++ b/src/common/tracker/Artifact.class.php
@@ -127,9 +127,16 @@ class Artifact extends FFObject {
        /**
         * Database result set of related tasks
         *
-        * @var result  $relatedtasks
+        * @var result  $related_tasks
         */
-       var $relatedtasks;
+       var $related_tasks;
+
+       /**
+        * Database result set of children
+        *
+        * @var result  $children
+        */
+       var $children;
 
        /**
         * cached return value of getVotes
@@ -766,8 +773,8 @@ class Artifact extends FFObject {
         * @return      resource        Database result set
         */
        function getRelatedTasks() {
-               if (!$this->relatedtasks) {
-                       $this->relatedtasks = db_query_params ('SELECT 
pt.group_project_id,pt.project_task_id,pt.summary,pt.start_date,pt.end_date,pgl.group_id,pt.status_id,pt.percent_complete,ps.status_name
+               if (!$this->related_tasks) {
+                       $this->related_tasks = db_query_params ('SELECT 
pt.group_project_id,pt.project_task_id,pt.summary,pt.start_date,pt.end_date,pgl.group_id,pt.status_id,pt.percent_complete,ps.status_name
                        FROM project_task pt, project_group_list pgl, 
project_status ps
                        WHERE pt.group_project_id = pgl.group_project_id
                         AND ps.status_id = pt.status_id
@@ -776,7 +783,7 @@ class Artifact extends FFObject {
                                AND artifact_id = $1)',
                                                               array 
($this->getID())) ;
                }
-               return $this->relatedtasks;
+               return $this->related_tasks;
        }
 
        /**
@@ -1582,7 +1589,7 @@ class Artifact extends FFObject {
                        // 3) Ensure that only integers are given.
                        // 4) Ensure that id corresponds to valid tracker id.
                        //
-                       if ($type == ARTIFACT_EXTRAFIELDTYPE_RELATION) {
+                       if ($type == ARTIFACT_EXTRAFIELDTYPE_RELATION || $type 
== ARTIFACT_EXTRAFIELDTYPE_PARENT) {
                                $value = preg_replace('/\[\#(\d+)\]/', "\\1", 
trim($extra_fields[$efid]));
                                $value = preg_replace('/\\s+/', ' ', $value);
                                $new = '';
@@ -1919,6 +1926,7 @@ class Artifact extends FFObject {
                                case ARTIFACT_EXTRAFIELDTYPE_TEXT:
                                case ARTIFACT_EXTRAFIELDTYPE_TEXTAREA:
                                case ARTIFACT_EXTRAFIELDTYPE_RELATION:
+                               case ARTIFACT_EXTRAFIELDTYPE_PARENT:
                                case ARTIFACT_EXTRAFIELDTYPE_INTEGER:
                                case ARTIFACT_EXTRAFIELDTYPE_DATE:
                                case ARTIFACT_EXTRAFIELDTYPE_DATETIME:
@@ -2050,6 +2058,80 @@ class Artifact extends FFObject {
                return false;
        }
 
+       function  getRelations() {
+               $aid = $this->getID();
+               $res = db_query_params ('SELECT *
+               FROM artifact_extra_field_list, artifact_extra_field_data, 
artifact_group_list, artifact, groups
+               WHERE field_type = $1
+               AND 
artifact_extra_field_list.extra_field_id=artifact_extra_field_data.extra_field_id
+               AND artifact_group_list.group_artifact_id = 
artifact_extra_field_list.group_artifact_id
+               AND artifact.artifact_id = artifact_extra_field_data.artifact_id
+               AND groups.group_id = artifact_group_list.group_id
+               AND (field_data = $2 OR field_data LIKE $3 OR field_data LIKE 
$4 OR field_data LIKE $5)
+               AND artifact.is_deleted = 0
+               ORDER BY artifact_group_list.group_id ASC, name ASC, 
artifact.artifact_id ASC',
+                               array(ARTIFACT_EXTRAFIELDTYPE_RELATION,
+                                               $aid,
+                                               "$aid %",
+                                               "% $aid %",
+                                               "% $aid"));
+               return $res;
+       }
+
+       function hasChildren() {
+               if (!$this->children) {
+                       $res = $this->getChildren();
+               }
+               $nb = db_numrows($this->children);
+               if ($nb>0) {
+                       return $nb;
+               }
+               return false;
+       }
+
+       function  getChildren() {
+               $aid = $this->getID();
+               if (!$this->children) {
+                       $this->children = db_query_params ('SELECT *
+               FROM artifact_extra_field_list, artifact_extra_field_data, 
artifact_group_list, artifact, groups
+               WHERE field_type = $1
+               AND 
artifact_extra_field_list.extra_field_id=artifact_extra_field_data.extra_field_id
+               AND artifact_group_list.group_artifact_id = 
artifact_extra_field_list.group_artifact_id
+               AND artifact.artifact_id = artifact_extra_field_data.artifact_id
+               AND groups.group_id = artifact_group_list.group_id
+               AND field_data = $2
+               AND artifact.is_deleted = 0
+               ORDER BY artifact_group_list.group_id ASC, name ASC, 
artifact.artifact_id ASC',
+                                       array(ARTIFACT_EXTRAFIELDTYPE_PARENT,
+                                                       $aid));
+               }
+               return $this->children;
+       }
+
+       function hasParent() {
+               return ($this->getParent?true:false);
+       }
+
+       function  getParent() {
+               $res = db_query_params ('SELECT field_data FROM
+                                                                       
artifact_extra_field_data
+                                                                       NATURAL 
INNER JOIN artifact_extra_field_list
+                                                               WHERE
+                                                                       
field_type = $1
+                                                                               
AND artifact_id = $2',
+                                       array(ARTIFACT_EXTRAFIELDTYPE_PARENT,
+                                                       $this->getID()));
+               if (db_numrows($res) == 0) {
+                       $return = false;
+               } else {
+                       $data = db_fetch_array($res);
+                       db_free_result($res);
+                       $return = $data['field_data'];
+               }
+               return $return;
+       }
+
+
        function getPermalink() {
                return '/tracker/a_follow.php/'.$this->getID();
        }
diff --git a/src/common/tracker/ArtifactExtraField.class.php 
b/src/common/tracker/ArtifactExtraField.class.php
index 6f83370..36af66c 100644
--- a/src/common/tracker/ArtifactExtraField.class.php
+++ b/src/common/tracker/ArtifactExtraField.class.php
@@ -51,6 +51,7 @@ define('ARTIFACT_EXTRAFIELDTYPE_DATETIMERANGE', 19);
 define('ARTIFACT_EXTRAFIELDTYPE_DATERANGE', 20);
 define('ARTIFACT_EXTRAFIELDTYPE_EFFORT',21);
 define('ARTIFACT_EXTRAFIELDTYPE_EFFORTRANGE',22);
+define('ARTIFACT_EXTRAFIELDTYPE_PARENT',23);
 
 define ("ARTIFACT_EXTRAFIELDTYPEGROUP_SINGLECHOICE", serialize (array 
(ARTIFACT_EXTRAFIELDTYPE_SELECT, ARTIFACT_EXTRAFIELDTYPE_RADIO, 
ARTIFACT_EXTRAFIELDTYPE_STATUS)));
 define ("ARTIFACT_EXTRAFIELDTYPEGROUP_MULTICHOICE", serialize (array 
(ARTIFACT_EXTRAFIELDTYPE_CHECKBOX, ARTIFACT_EXTRAFIELDTYPE_MULTISELECT)));
@@ -58,6 +59,15 @@ define ("ARTIFACT_EXTRAFIELDTYPEGROUP_CHOICE", serialize 
(array_merge(unserializ
 define ("ARTIFACT_EXTRAFIELDTYPEGROUP_SPECALCHOICE", 
serialize(array(ARTIFACT_EXTRAFIELDTYPE_USER, 
ARTIFACT_EXTRAFIELDTYPE_RELEASE)));
 define ("ARTIFACT_EXTRAFIELDTYPEGROUP_VALUE", serialize (array 
(ARTIFACT_EXTRAFIELDTYPE_TEXT,ARTIFACT_EXTRAFIELDTYPE_TEXTAREA,ARTIFACT_EXTRAFIELDTYPE_RELATION,ARTIFACT_EXTRAFIELDTYPE_INTEGER,ARTIFACT_EXTRAFIELDTYPE_FORMULA,ARTIFACT_EXTRAFIELDTYPE_DATETIME,
 ARTIFACT_EXTRAFIELDTYPE_EFFORT)));
 
+define ("ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_NO_AGGREGATION", 0);
+define ("ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_SUM", 1);
+define ("ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_STATUS_CLOSE_RESTRICTED", 2);
+define ("ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_STATUS_CLOSE_UPWARDS", 3);
+
+define ("ARTIFACT_EXTRAFIELD_DISTRIBUTION_RULE_NO_DISTRIBUTION", 0);
+define ("ARTIFACT_EXTRAFIELD_DISTRIBUTION_RULE_STATUS_CLOSE_RECURSIVELY", 1);
+
+
 class ArtifactExtraField extends FFError {
 
        /**
@@ -123,7 +133,7 @@ class ArtifactExtraField extends FFError {
         * @param       int     $disabled               True or false to 
enable/disable the extrafield
         * @return      bool    true on success / false on failure.
         */
-       function create($name, $field_type, $attribute1, $attribute2, 
$is_required = 0, $alias = '', $show100 = true, $show100label = 'none', 
$description = '', $pattern = '', $parent = 100, $autoassign = 0, 
$is_hidden_on_submit = 0, $is_disabled = 0) {
+       function create($name, $field_type, $attribute1, $attribute2, 
$is_required = 0, $alias = '', $show100 = true, $show100label = 'none', 
$description = '', $pattern = '', $parent = 100, $autoassign = 0, 
$is_hidden_on_submit = 0, $is_disabled = 0, $aggregation_rule = 0, 
$distribution_rule = 0) {
                //
                //      data validation
                //
@@ -177,8 +187,8 @@ class ArtifactExtraField extends FFError {
                }
 
                db_begin();
-               $result = db_query_params ('INSERT INTO 
artifact_extra_field_list (group_artifact_id, field_name, field_type, 
attribute1, attribute2, is_required, alias, show100, show100label, description, 
pattern, parent, is_hidden_on_submit, is_disabled)
-                       VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)',
+               $result = db_query_params ('INSERT INTO 
artifact_extra_field_list (group_artifact_id, field_name, field_type, 
attribute1, attribute2, is_required, alias, show100, show100label, description, 
pattern, parent, is_hidden_on_submit, is_disabled, aggregation_rule, 
distribution_rule)
+                       VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)',
                                           array ($this->ArtifactType->getID(),
                                                          
htmlspecialchars($name),
                                                          $field_type,
@@ -192,7 +202,9 @@ class ArtifactExtraField extends FFError {
                                                          $pattern,
                                                          $parent,
                                                          $is_hidden_on_submit,
-                                                         $is_disabled));
+                                                         $is_disabled,
+                                                         $aggregation_rule,
+                                                         $distribution_rule));
 
                if ($result && db_affected_rows($result) > 0) {
                        $this->clearError();
@@ -760,7 +772,8 @@ class ArtifactExtraField extends FFError {
                        ARTIFACT_EXTRAFIELDTYPE_RELEASE => _('Release'),
                        ARTIFACT_EXTRAFIELDTYPE_EFFORT => _('Effort'),
                        ARTIFACT_EXTRAFIELDTYPE_FORMULA => _('Formula'),
-                       ARTIFACT_EXTRAFIELDTYPE_SLA => _('SLA')
+                       ARTIFACT_EXTRAFIELDTYPE_SLA => _('SLA'),
+                       ARTIFACT_EXTRAFIELDTYPE_PARENT => _('Parent artifact')
                        );
        }
 
@@ -896,7 +909,7 @@ class ArtifactExtraField extends FFError {
         * @param       int     $parent         Parent extra field id.
         * @return      bool    success.
         */
-       function update($name, $attribute1, $attribute2, $is_required = 0, 
$alias = "", $show100 = true, $show100label = 'none', $description = '', 
$pattern = '', $parent = 100, $autoassign = 0, $is_hidden_on_submit = 0, 
$is_disabled = 0) {
+       function update($name, $attribute1, $attribute2, $is_required = 0, 
$alias = "", $show100 = true, $show100label = 'none', $description = '', 
$pattern = '', $parent = 100, $autoassign = 0, $is_hidden_on_submit = 0, 
$is_disabled = 0, $aggregation_rule = 0, $distribution_rule = 0) {
                if (!forge_check_perm ('tracker_admin', 
$this->ArtifactType->Group->getID())) {
                        $this->setPermissionDeniedError();
                        return false;
@@ -940,9 +953,11 @@ class ArtifactExtraField extends FFError {
                        pattern = $9,
                        parent = $10,
                        is_hidden_on_submit = $11,
-                       is_disabled = $12
-                       WHERE extra_field_id = $13
-                       AND group_artifact_id = $14',
+                       is_disabled = $12,
+                       aggregation_rule = $13,
+                       distribution_rule = $14
+                       WHERE extra_field_id = $15
+                       AND group_artifact_id = $16',
                                           array (htmlspecialchars($name),
                                                          $description,
                                                          $attribute1,
@@ -955,6 +970,8 @@ class ArtifactExtraField extends FFError {
                                                          $parent,
                                                          $is_hidden_on_submit,
                                                          $is_disabled,
+                                                         $aggregation_rule,
+                                                         $distribution_rule,
                                                          $this->getID(),
                                                          
$this->ArtifactType->getID())) ;
                if ($result && db_affected_rows($result) > 0) {
@@ -1176,7 +1193,6 @@ class ArtifactExtraField extends FFError {
        }
 
        function alphaorderValues() {
-
                $res = db_query_params ('SELECT element_id FROM 
artifact_extra_field_elements WHERE extra_field_id=$1 ORDER BY element_name 
ASC',
                        array($this->getID()));
                $i = 1;
@@ -1185,11 +1201,11 @@ class ArtifactExtraField extends FFError {
                                return false;
                        $i++;
                }
-
                return true;
        }
 
        /**
+<<<<<<< 5c02d437ae2ab9d01370cc9aec4ecc46f3602746
         *    getMandatoryExtraFields - List of possible user built extra fields
         *    set up for this artifact type.
         *
@@ -1258,7 +1274,54 @@ class ArtifactExtraField extends FFError {
 
                return $return;
        }
+       
+       /**
+        * getAvailableAggregationRules - the types of text fields and their 
names available.
+        *
+        * @return      array   rules.
+        */
+       function getAvailableAggregationRules() {
+               $return= 
array(ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_NO_AGGREGATION => _('Parent value is 
not depending on children\'s values'));
+               $type = $this->getType();
+               if ($type == ARTIFACT_EXTRAFIELDTYPE_EFFORT) {
+                       $return = array_merge($return, 
array(ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_SUM => _('Parent value is the sum of 
children\'s values')));
+               }
+               if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
+                       $return = array_merge($return, array(
+                                                                               
                        
ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_STATUS_CLOSE_RESTRICTED => _('Deny closing 
the parent, as long as not all children have been closed'),
+                                                                               
                        
ARTIFACT_EXTRAFIELD_AGGREGATION_RULE_STATUS_CLOSE_UPWARDS => _('Close the 
parent, after the last child has been closed')
+                                                               ));
+               }
+               if (count($return)==1) {
+                       $return = array();
+               }
+               return $return;
+       }
+
+       function getAggregationRule() {
+               return $this->data_array['aggregation_rule'];
+       }
 
+       /**
+       * getAvailableDistributionRules- the types of text fields and their 
names available.
+       *
+       * @return       array   rules.
+       */
+       function getAvailableDistributionRules() {
+               $return= 
array(ARTIFACT_EXTRAFIELD_DISTRIBUTION_RULE_NO_DISTRIBUTION => _('Parent value 
is not depending on children\'s values'));
+               $type = $this->getType();
+               if ($type == ARTIFACT_EXTRAFIELDTYPE_STATUS) {
+                       $return = array_merge($return, 
array(ARTIFACT_EXTRAFIELD_DISTRIBUTION_RULE_STATUS_CLOSE_RECURSIVELY => 
_('Closure of parent involves recursive closure of children')));
+               }
+               if (count($return)==1) {
+                       $return = array();
+               }
+               return $return;
+       }
+
+       function getDistributionRule() {
+               return $this->data_array['distribution_rule'];
+       }
 }
 
 // Local Variables:
diff --git a/src/common/tracker/actions/admin-updates.php 
b/src/common/tracker/actions/admin-updates.php
index 8859b4d..d3eb823 100644
--- a/src/common/tracker/actions/admin-updates.php
+++ b/src/common/tracker/actions/admin-updates.php
@@ -249,6 +249,8 @@ if (getStringFromRequest('add_extrafield')) {
        $is_disabled = getStringFromRequest('is_disabled');
        $defaultArr = getArrayFromRequest('extra_fields', false);
        $formula = getStringFromRequest('formula');
+       $aggregation_rule = getIntFromRequest('aggregation_rule',0);
+       $distribution_rule = getIntFromRequest('distribution_rule',0);
        if (isset($defaultArr[$id])) {
                $default = $defaultArr[$id];
        } else {
@@ -266,7 +268,7 @@ if (getStringFromRequest('add_extrafield')) {
                } else {
                        $show100 = 1;
                }
-               if (!$ac->update($name, $attribute1, $attribute2, $is_required, 
$alias, $show100, $show100label, $description, $pattern, $parent, $autoassign, 
$is_hidden_on_submit, $is_disabled)) {
+               if (!$ac->update($name, $attribute1, $attribute2, $is_required, 
$alias, $show100, $show100label, $description, $pattern, $parent, $autoassign, 
$is_hidden_on_submit, $is_disabled, $aggregation_rule, $distribution_rule)) {
                        $error_msg .= _('Update failed')._(': 
').$ac->getErrorMessage();
                        $ac->clearError();
                } elseif (!$ac->setFormula($formula)){
diff --git a/src/common/tracker/actions/detail.php 
b/src/common/tracker/actions/detail.php
index 21aacdf..eec9623 100644
--- a/src/common/tracker/actions/detail.php
+++ b/src/common/tracker/actions/detail.php
@@ -141,20 +141,34 @@ foreach ($pluginsListeners as $pluginsListener) {
                break;
        }
 }
+$count=db_numrows($ah->getHistory());
+$nbh = $count? ' ('.$count.')' : '';
 ?>
 <div id="tabber">
        <ul>
        <li><a href="#tabber-comments"><?php echo _('Comments').$nb; ?></a></li>
-       <?php if ($group->usesPM()) { ?>
-       <li><a href="#tabber-tasks"><?php echo _('Related Tasks'); ?></a></li>
+       <?php if ($group->usesPM()) {
+               $count= db_numrows($ah->getRelatedTasks());
+               $nbrt = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-tasks"><?php echo _('Related Tasks').$nbrt; 
?></a></li>
        <?php } ?>
        <li><a href="#tabber-attachments"><?php echo _('Attachments').$nbf; 
?></a></li>
        <?php if ($pluginfound) { ?>
        <li><a href="#tabber-commits"><?php echo _('Commits'); ?></a></li>
        <?php } ?>
-       <li><a href="#tabber-changes"><?php echo _('Changes'); ?></a></li>
-       <?php if ($ah->hasRelations()) { ?>
-       <li><a href="#tabber-relations"><?php echo _('Relations'); ?></a></li>
+       <li><a href="#tabber-changes"><?php echo _('Changes').$nbh; ?></a></li>
+       <?php if ($ah->hasRelations()) {
+               $count=db_numrows($ah->getRelations());
+               $nbr = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-relations"><?php echo _('Relations').$nbr; 
?></a></li>
+       <?php } ?>
+       <?php if (forge_get_config('use_artefacts_dependencies')) {
+               $count=$ah->hasChildren();
+               $nbc = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-children"><?php echo _('Children').$nbc; 
?></a></li>
        <?php } ?>
        <?php if (forge_get_config('use_object_associations')) {
                $anf = '';
@@ -232,7 +246,14 @@ if ($group->usesPM()) {
        <div id="tabber-changes" class="tabbertab">
                <?php echo $ah->showHistory(); ?>
        </div>
-       <?php echo $ah->showRelations();
+       <div id="tabber-relations" class="tabbertab">
+       <?php echo $ah->showRelations(); ?>
+       </div><?php
+       if (forge_get_config('use_artefacts_dependencies')) { ?>
+               <div id="tabber-children" class="tabbertab">
+                       <?php echo $ah->showChildren(); ?>
+               </div><?php
+       }
        if (forge_get_config('use_object_associations')) { ?>
        <div id="tabber-object-associations" class="tabbertab">
        <?php if (forge_check_perm ('tracker',$ath->getID(),'submit')) {
diff --git a/src/common/tracker/actions/effort_units.php 
b/src/common/tracker/actions/effort_units.php
index 83da421..d6314a2 100644
--- a/src/common/tracker/actions/effort_units.php
+++ b/src/common/tracker/actions/effort_units.php
@@ -549,7 +549,6 @@ function postcopy_set(&$effortUnitSet) {
 function update_set(&$effortUnitSet) {
        global $HTML;
        $isAutoconvert = (getStringFromRequest('is_autoconvert')=='on'?1:0);
-       var_dump($isAutoconvert);
        if (!$effortUnitSet->update($isAutoconvert)) {
                echo $HTML->error_msg(_('Error updating Effort Unit 
Set')._(':').' '.$effortUnitSet->getErrorMessage());
                return false;
diff --git a/src/common/tracker/actions/mod-limited.php 
b/src/common/tracker/actions/mod-limited.php
index 9fca9bd..7437b01 100644
--- a/src/common/tracker/actions/mod-limited.php
+++ b/src/common/tracker/actions/mod-limited.php
@@ -181,19 +181,33 @@ foreach ($pluginsListeners as $pluginsListener) {
                break;
        }
 }
+$count=db_numrows($ah->getHistory());
+$nbh = $count? ' ('.$count.')' : '';
 ?>
        <ul>
        <li><a href="#tabber-comments"><?php echo _('Comments').$nb; ?></a></li>
-       <?php if ($group->usesPM()) { ?>
-       <li><a href="#tabber-tasks"><?php echo _('Related Tasks'); ?></a></li>
+       <?php if ($group->usesPM()) {
+               $count= db_numrows($ah->getRelatedTasks());
+               $nbrt = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-tasks"><?php echo _('Related Tasks').$nbrt; 
?></a></li>
        <?php } ?>
        <li><a href="#tabber-attachments"><?php echo _('Attachments').$nbf; 
?></a></li>
        <?php if ($pluginfound) { ?>
        <li><a href="#tabber-commits"><?php echo _('Commits'); ?></a></li>
        <?php } ?>
-       <li><a href="#tabber-changes"><?php echo _('Changes'); ?></a></li>
-       <?php if ($ah->hasRelations()) { ?>
-       <li><a href="#tabber-relations"><?php echo _('Relations'); ?></a></li>
+       <li><a href="#tabber-changes"><?php echo _('Changes').$nbh; ?></a></li>
+       <?php if ($ah->hasRelations()) {
+               $count=db_numrows($ah->getRelations());
+               $nbr = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-relations"><?php echo _('Relations').$nbr; 
?></a></li>
+       <?php } ?>
+       <?php if (forge_get_config('use_artefacts_dependencies')) {
+               $count=$ah->hasChildren();
+               $nbc = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-children"><?php echo _('Children').$nbc; 
?></a></li>
        <?php } ?>
        <?php if (forge_get_config('use_object_associations')) {
                $anf = '';
@@ -257,7 +271,14 @@ echo $ath->renderFiles($group_id, $ah);
 <div id="tabber-changes" class="tabbertab">
        <?php echo $ah->showHistory(); ?>
 </div>
-<?php echo $ah->showRelations();
+<div id="tabber-relations" class="tabbertab">
+       <?php echo $ah->showRelations(); ?>
+</div><?php
+if (forge_get_config('use_artefacts_dependencies')) { ?>
+       <div id="tabber-children" class="tabbertab">
+               <?php echo $ah->showChildren(); ?>
+       </div><?php
+}
 if (forge_get_config('use_object_associations')) { ?>
 <div id="tabber-object-associations" class="tabbertab">
        <?php if (forge_check_perm ('tracker',$ath->getID(),'submit')) {
diff --git a/src/common/tracker/actions/mod.php 
b/src/common/tracker/actions/mod.php
index 5f9e714..31e2ffd 100644
--- a/src/common/tracker/actions/mod.php
+++ b/src/common/tracker/actions/mod.php
@@ -238,22 +238,36 @@ foreach ($pluginsListeners as $pluginsListener) {
                break;
        }
 }
+$count=db_numrows($ah->getHistory());
+$nbh = $count? ' ('.$count.')' : '';
 ?>
        <ul>
        <li><a href="#tabber-comments"><?php echo _('Comments').$nb; ?></a></li>
-       <?php if ($group->usesPM()) { ?>
-       <li><a href="#tabber-tasks"><?php echo _('Related Tasks'); ?></a></li>
+       <?php if ($group->usesPM()) {
+               $count= db_numrows($ah->getRelatedTasks());
+               $nbrt = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-tasks"><?php echo _('Related Tasks').$nbrt; 
?></a></li>
        <?php } ?>
        <li><a href="#tabber-attachments"><?php echo _('Attachments').$nbf; 
?></a></li>
        <?php if ($pluginfound) { ?>
        <li><a href="#tabber-commits"><?php echo _('Commits'); ?></a></li>
        <?php } ?>
-       <li><a href="#tabber-changes"><?php echo _('Changes'); ?></a></li>
-       <?php if ($ah->hasRelations()) { ?>
-       <li><a href="#tabber-relations"><?php echo _('Relations'); ?></a></li>
+       <li><a href="#tabber-changes"><?php echo _('Changes').$nbh; ?></a></li>
+       <?php if ($ah->hasRelations()) {
+               $count=db_numrows($ah->getRelations());
+               $nbr = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-relations"><?php echo _('Relations').$nbr; 
?></a></li>
+       <?php } ?>
+       <?php if (forge_get_config('use_artefacts_dependencies')) {
+               $count=$ah->hasChildren();
+               $nbc = $count? ' ('.$count.')' : '';
+       ?>
+       <li><a href="#tabber-children"><?php echo _('Children').$nbc; 
?></a></li>
        <?php } ?>
        <?php if (forge_get_config('use_object_associations')) {
-                       $anf = '';
+               $anf = '';
                if ($ah->getAssociationCounter()) {
                        $anf = ' ('.$ah->getAssociationCounter().')';
                } ?>
@@ -335,8 +349,15 @@ echo $ath->renderFiles($group_id, $ah);
 <div id="tabber-changes" class="tabbertab">
        <?php echo $ah->showHistory(); ?>
 </div>
-       <?php echo $ah->showRelations();
-       if (forge_get_config('use_object_associations')) { ?>
+<div id="tabber-relations" class="tabbertab">
+       <?php echo $ah->showRelations(); ?>
+</div><?php
+if (forge_get_config('use_artefacts_dependencies')) { ?>
+       <div id="tabber-children" class="tabbertab">
+               <?php echo $ah->showChildren(); ?>
+       </div><?php
+}
+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/include/ArtifactHtml.class.php 
b/src/common/tracker/include/ArtifactHtml.class.php
index 58b0cad..2f3bbfc 100644
--- a/src/common/tracker/include/ArtifactHtml.class.php
+++ b/src/common/tracker/include/ArtifactHtml.class.php
@@ -189,33 +189,51 @@ function hide_edit_button(id) {
        }
 
        function showRelations() {
-               $aid = $this->getID();
+               $result=$this->getRelations();
+               $rows= db_numrows($result);
                $return = '';
+               if ($rows > 0){
+                       $return = '<table class="fullwidth">
+                                                       <tr>
+                                                               <td 
colspan="2">';
+                       $current = '';
+                       $end = '';
+                       while ($arr = db_fetch_array($result)) {
+                               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'].']';
+                                       $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).' '.util_make_link($url, $arr['summary']).' <i>('._('Relation')._(': 
').$arr['field_name'].')</i>';
+                               }
+                       }
+                       $return .= '</td>
+                               </tr>
+                               </table>';
+               }
+               return $return;
+       }
 
-               // Search for all relations pointing to this record.
-
-               $res = db_query_params ('SELECT *
-               FROM artifact_extra_field_list, artifact_extra_field_data, 
artifact_group_list, artifact, groups
-               WHERE field_type=9
-               AND 
artifact_extra_field_list.extra_field_id=artifact_extra_field_data.extra_field_id
-               AND artifact_group_list.group_artifact_id = 
artifact_extra_field_list.group_artifact_id
-               AND artifact.artifact_id = artifact_extra_field_data.artifact_id
-               AND groups.group_id = artifact_group_list.group_id
-               AND (field_data = $1 OR field_data LIKE $2 OR field_data LIKE 
$3 OR field_data LIKE $4)
-               AND artifact.is_deleted = 0
-               ORDER BY artifact_group_list.group_id ASC, name ASC, 
artifact.artifact_id ASC',
-                                       array($aid,
-                                             "$aid %",
-                                             "% $aid %",
-                                             "% $aid"));
-               if (db_numrows($res)>0) {
-                       $return = '<div id="tabber-relations" class="tabbertab">
-                                       <table class="fullwidth">
-                                               <tr>
-                                                       <td colspan="2">';
+       function showChildren() {
+               $result=$this->getChildren();
+               $rows= db_numrows($result);
+               $return = '';
+               if ($rows > 0){
+                       $return = '     <table class="fullwidth">
+                                                       <tr>
+                                                               <td 
colspan="2">';
                        $current = '';
                        $end = '';
-                       while ($arr = db_fetch_array($res)) {
+                       while ($arr = db_fetch_array($result)) {
                                if (forge_check_perm('tracker', 
$arr['group_artifact_id'], 'read')) {
                                        $title = $arr['group_name']._(': 
').$arr['name'];
                                        if ($title != $current) {
@@ -223,20 +241,19 @@ function hide_edit_button(id) {
                                                $current = $title;
                                                $end = '<br /><br />';
                                        }
-                                       $text = '[#'.$arr['artifact_id'].']'.' 
'.$arr['summary'];
+                                       $text = '[#'.$arr['artifact_id'].']';
                                        $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>';
+                                       $return .= util_make_link($url, $text, 
$arg).' '.util_make_link($url, $arr['summary']).' <i>('._('Parent')._(': 
').$arr['field_name'].')</i>';
                                }
                        }
                        $return .= '</td>
                                </tr>
-                               </table>
-                               </div>';
+                               </table>';
                }
                return $return;
        }
diff --git a/src/common/tracker/include/ArtifactTypeHtml.class.php 
b/src/common/tracker/include/ArtifactTypeHtml.class.php
index 7d98202..db34f4c 100644
--- a/src/common/tracker/include/ArtifactTypeHtml.class.php
+++ b/src/common/tracker/include/ArtifactTypeHtml.class.php
@@ -199,6 +199,7 @@ class ArtifactTypeHtml extends ArtifactType {
                                $types = array(),
                                $status_show_100 = false,
                                $mode = '') {
+               global $HTML;
                if ($mode == 'NEW') {
                        $efarr = $this->getExtraFields($types, false, false);
                } else {
@@ -273,7 +274,7 @@ class ArtifactTypeHtml extends ArtifactType {
                                                $type == 
ARTIFACT_EXTRAFIELDTYPE_TEXTAREA) {
                                        $value = 
preg_replace('/((http|https|ftp):\/\/\S+)/',
                                                                "<a 
href=\"\\1\" target=\"_blank\">\\1</a>", $value);
-                               } elseif ($type == 
ARTIFACT_EXTRAFIELDTYPE_RELATION) {
+                               } elseif ($type == 
ARTIFACT_EXTRAFIELDTYPE_RELATION || $type == ARTIFACT_EXTRAFIELDTYPE_PARENT) {
                                        // Convert artifact id to links.
                                        $value = 
preg_replace_callback('/\b(\d+)\b/', create_function('$matches', 'return 
_artifactid2url($matches[1], \'title\');'), $value);
                                } elseif ($type == 
ARTIFACT_EXTRAFIELDTYPE_DATETIME && $value!='') {
@@ -399,10 +400,14 @@ class ArtifactTypeHtml extends ArtifactType {
                                $str = 
$this->renderSelect($efarr[$i]['extra_field_id'], $selected_node, 
$status_show_100, $text_100, $show_any, $text_any, $allowed, $attrs);
 
                        } elseif ($efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_RELATION) {
-
                                $str = 
$this->renderRelationField($efarr[$i]['extra_field_id'], 
$selected[$efarr[$i]['extra_field_id']], $efarr[$i]['attribute1'], 
$efarr[$i]['attribute2'], $attrs);
                                if ($mode == 'UPDATE' || $mode == 'NEW') {
-                                       $post_name = 
html_image('ic/forum_edit.png', 37, 15 ,array('title'=>"Click to edit", 
'alt'=>"Click to edit", 'onclick'=>"switch2edit(this, 'show$i', 'edit$i')"));
+                                       $post_name = 
$HTML->getEditFieldPic(_('Click to edit'), $alt = _('Click to edit'), 
array('onclick'=>"switch2edit(this, 'show$i', 'edit$i')"));
+                               }
+                       } elseif ($efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_PARENT) {
+                               $str = 
$this->renderParentField($efarr[$i]['extra_field_id'], 
$selected[$efarr[$i]['extra_field_id']], $efarr[$i]['attribute1'], 
$efarr[$i]['attribute2'], $attrs);
+                               if ($mode == 'UPDATE' || $mode == 'NEW') {
+                                       $post_name = 
$HTML->getEditFieldPic(_('Click to edit'), $alt = _('Click to edit'), 
array('onclick'=>"switch2edit(this, 'show$i', 'edit$i')"));
                                }
                        } elseif ($efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_DATETIME) {
                                $str = 
$this->renderDatetime($efarr[$i]['extra_field_id'], 
$selected[$efarr[$i]['extra_field_id']], $attrs);
@@ -601,6 +606,7 @@ class ArtifactTypeHtml extends ArtifactType {
                        } elseif ($efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_TEXT ||
                                $efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_INTEGER ||
                                $efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_RELATION ||
+                               $efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_PARENT ||
                                $efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_DATETIME ||
                                        $efarr[$i]['field_type'] == 
ARTIFACT_EXTRAFIELDTYPE_EFFORT) {
 
@@ -1115,6 +1121,7 @@ class ArtifactTypeHtml extends ArtifactType {
                        $keys[$i]=$arr[$i]['element_id'];
                        $vals[$i]=$arr[$i]['element_name'];
                }
+               $attrs['pattern']='^\d+(\s+\d+)*$';
                // Convert artifact id to links.
                $html_contents = preg_replace_callback('/\b(\d+)\b/', 
create_function('$matches', 'return _artifactid2url($matches[1], \'title\');'), 
$contents);
                $edit_contents = $this->renderTextField ($extra_field_id, 
$contents, $size, $maxlength);
@@ -1123,6 +1130,30 @@ class ArtifactTypeHtml extends ArtifactType {
        }
 
        /**
+        * renderParentField - this function builds a parent field.
+        *
+        * @param       int     $extra_field_id The ID of this field.
+        * @param       string  $contents       The data for this field.
+        * @param       string  $size
+        * @param       string  $maxlength
+        * @param       array   $attrs          Array of other attributes
+        * @return      string  text area and data.
+        */
+       function renderParentField($extra_field_id, $contents, $size, 
$maxlength, $attrs = array()) {
+               $arr = $this->getExtraFieldElements($extra_field_id);
+               for ($i=0; $i<count($arr); $i++) {
+                       $keys[$i]=$arr[$i]['element_id'];
+                       $vals[$i]=$arr[$i]['element_name'];
+               }
+               $attrs['pattern']='^\d*$';
+               // Convert artifact id to links.
+               $html_contents = preg_replace_callback('/\b(\d+)\b/', 
create_function('$matches', 'return _artifactid2url($matches[1], \'title\');'), 
$contents);
+               $edit_contents = $this->renderTextField ($extra_field_id, 
$contents, $size, $maxlength);
+               return 
html_e('div',array_merge(array('id'=>'edit'.$extra_field_id, 'style'=>'display: 
none', 'title'=>_('Tip: Enter a space-separated list of artifact ids ([#NNN] 
also accepted)')), $attrs), $edit_contents)
+               .html_e('div',array_merge(array('id'=>'show'.$extra_field_id, 
'style'=>'display: block'), $attrs), $html_contents);
+       }
+
+       /**
         * renderTextArea - this function builds a text area.
         *
         * @param       int     $extra_field_id The ID of this field.
@@ -1548,6 +1579,7 @@ EOS;
                        data: 
'rtype=ajax&function=get_formulas_results&group_id='+groupId+'&atid='+atId+'&status='+$("select[name='status_id']
 option:selected").text()+'&assigned_to='+$("select[name='assigned_to'] 
option:selected").text()+'&'+$("[name^='extra_fields'], #tracker-summary, 
#tracker-description, [name='priority']").serialize(),
                        async: false,
                        dataType: 'json',
+                       contentType:"application/json; charset=utf-8",
                        success: function(answer){
                                if(answer['message']) {
                                        showMessage(answer['message'], 'error');
diff --git a/src/common/tracker/views/form-addextrafield.php 
b/src/common/tracker/views/form-addextrafield.php
index a9f454c..250a70a 100644
--- a/src/common/tracker/views/form-addextrafield.php
+++ b/src/common/tracker/views/form-addextrafield.php
@@ -221,7 +221,8 @@ $jsvariable ="
        var typeDateTime = ".ARTIFACT_EXTRAFIELDTYPE_DATETIME.";
        var typeUser = ".ARTIFACT_EXTRAFIELDTYPE_USER.";
        var typeRelease = ".ARTIFACT_EXTRAFIELDTYPE_RELEASE.";
-       var typeEffort = ".ARTIFACT_EXTRAFIELDTYPE_EFFORT.";";
+       var typeEffort = ".ARTIFACT_EXTRAFIELDTYPE_EFFORT.";
+       var typeParent = ".ARTIFACT_EXTRAFIELDTYPE_PARENT.";";
 
 $javascript = <<<'EOS'
        $("p[class^='for-']").hide();
@@ -294,6 +295,12 @@ $javascript = <<<'EOS'
                $("p.for-effort").show();
                $("p[class^='for-']:not(.for-effort)").hide();
        });
+       $("input[value="+typeParent+"]").on('change', function(){
+               $("label[for='attribute1']").text(size);
+               $("label[for='attribute2']").text(maxLength);
+               $("p.for-parent").show();
+               $("p[class^='for-']:not(.for-parent)").hide();
+       });
 
 EOS;
 echo html_e('script', array( 'type'=>'text/javascript'), 
'//<![CDATA['."\n".'$(function(){'.$jsvariable."\n".$javascript.'});'."\n".'//]]>');
@@ -303,12 +310,17 @@ echo html_e('strong', array(), _('Type of custom 
field').utils_requiredField()._
 if ($ath->usesCustomStatuses()) {
        unset($eftypes[ARTIFACT_EXTRAFIELDTYPE_STATUS]);
 }
+
+if (!forge_get_config('use_artefacts_dependencies')) {
+       unset($eftypes[ARTIFACT_EXTRAFIELDTYPE_PARENT]);
+}
+
 $vals = array_keys($eftypes);
 $texts = array_values($eftypes);
 echo html_build_radio_buttons_from_arrays($vals, $texts, 'field_type', '', 
false, '', false ,'', false, array('required'=>'required') );
 echo html_ac(html_ap() - 1);
 
-echo html_ao('p', array('class'=>'for-text for-textarea for-integer 
for-relation for-effort'));
+echo html_ao('p', array('class'=>'for-text for-textarea for-integer 
for-relation for-effort for-parent'));
 echo html_e('label', array('for'=>'attribute1'), _('Size')._(':'));
 echo html_e('input', array('type'=>'text', 'name'=>'attribute1', 
'value'=>'20', 'size'=>'2', 'maxlength'=>'2')).html_e('br');
 echo html_e('label', array('for'=>'attribute2'), _('Maxlength')._(':'));
diff --git a/src/common/tracker/views/form-editformula.php 
b/src/common/tracker/views/form-editformula.php
index 38cd5ae..6001baf 100644
--- a/src/common/tracker/views/form-editformula.php
+++ b/src/common/tracker/views/form-editformula.php
@@ -27,9 +27,6 @@ global $HTML;
 
 html_use_tablesorter();
 
-$title = sprintf(_('Manage Custom Fields for %s'), $ath->getName());
-$ath->adminHeader(array('title'=>$title, 'modal'=>1));
-
 $boxid = getIntFromRequest('boxid');
 if ($boxid) {
        $ef_id = $boxid;
@@ -46,6 +43,9 @@ if (!$ac || !is_object($ac)) {
        exit_error($ac->getErrorMessage());
 }
 
+$title = sprintf(_('Edit formula for %s'), $ath->getName());
+$ath->adminHeader(array('title'=>$title, 'modal'=>1));
+
 if (!$efe_id) {
        $formula = $ac->getFormula();
 } else {
@@ -57,7 +57,6 @@ if (!$efe_id) {
        }
        $formula = $ao->getFormula();
 }
-
 $efarr = $ath->getExtraFields(array(),false,true);
 $efarr [] = array('field_name'=>'Assigned to','alias'=>'assigned_to', 
'field_type'=>ARTIFACT_EXTRAFIELDTYPE_USER,'extra_field_id'=>0);
 $efarr [] = array('field_name'=>'Priority','alias'=>'priority', 
'field_type'=>ARTIFACT_EXTRAFIELDTYPE_SELECT, 'extra_field_id'=>0);
@@ -252,7 +251,7 @@ $("textarea#formula").keydown(function(e) {
 EOS;
 echo html_e('script', array('type'=>'text/javascript'), 
'//<![CDATA['."\n".'$(function(){'.$javascript.'});'."\n".'//]]>');
 
-echo html_e('h2', array(), _('Edit formula'));
+echo html_e('h2', array(), _('Formula'));
 
 if (!$efe_id) {
        echo $HTML->openForm(array('action' => 
'/tracker/admin/?group_id='.$group_id.'&id='.$ef_id.'&atid='.$ath->getID(), 
'method' => 'post'));
diff --git a/src/common/tracker/views/form-updateextrafield.php 
b/src/common/tracker/views/form-updateextrafield.php
index 2f2e05c..16e65ee 100644
--- a/src/common/tracker/views/form-updateextrafield.php
+++ b/src/common/tracker/views/form-updateextrafield.php
@@ -209,6 +209,21 @@ if (!$ac || !is_object($ac)) {
                echo html_e('input', array('type'=>'hidden', 'name'=>'formula', 
'value'=>''));
        }
 
+       $aggregationRules = $ac->getAvailableAggregationRules();
+       if (!empty($aggregationRules)) {
+               echo html_ao('p');
+               echo html_e('label', array('for'=>'aggregation_rule'), 
_('Dependency of parents on children'));
+               echo 
html_build_select_box_from_arrays(array_keys($aggregationRules), 
array_values($aggregationRules), 'aggregation_rule', $ac->getAggregationRule(), 
false).html_e('br');
+               echo html_ac(html_ap() - 1);
+       }
+       $distributionRules = $ac->getAvailableDistributionRules();
+       if (!empty($distributionRules)) {
+               echo html_ao('p');
+               echo html_e('label', array('for'=>'distribution_rule'), 
_('Dependency of children on parents'));
+               echo 
html_build_select_box_from_arrays(array_keys($distributionRules), 
array_values($distributionRules), 'distribution_rule', 
$ac->getDistributionRule(), false).html_e('br');
+               echo html_ac(html_ap() - 1);
+       }
+
        echo $HTML->warning_msg(_('It is not recommended that you change the 
custom field name because other things are dependent upon it. When you change 
the custom field name, all related items will be changed to the new name.'));
 
        echo html_ao('p');
diff --git a/src/common/widget/Widget_TrackerComment.class.php 
b/src/common/widget/Widget_TrackerComment.class.php
index db51547..3aa56d5 100644
--- a/src/common/widget/Widget_TrackerComment.class.php
+++ b/src/common/widget/Widget_TrackerComment.class.php
@@ -67,7 +67,9 @@ class Widget_TrackerComment extends Widget {
                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));
+                               $count= db_numrows($ah->getRelatedTasks());
+                               $nbrt = $count? ' ('.$count.')' : '';
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-tasks', _('Related Tasks').$nbrt, false, true));
                        }
                }
                $elementsLi[] = array('content' => 
util_make_link('#tabber-attachments', _('Attachments').$nbf, false, true));
@@ -85,9 +87,21 @@ class Widget_TrackerComment extends Widget {
                        if ($pluginfound) {
                                $elementsLi[] = array('content' => 
util_make_link('#tabber-commits', _('Commits'), false, true));
                        }
-                       $elementsLi[] = array('content' => 
util_make_link('#tabber-changes', _('Changes'), false, true));
+                       $count=db_numrows($ah->getHistory());
+                       $nbh = $count? ' ('.$count.')' : '';
+                       $elementsLi[] = array('content' => 
util_make_link('#tabber-changes', _('Changes').$nbh, false, true));
                        if ($ah->hasRelations()) {
-                               $elementsLi[] = array('content' => 
util_make_link('#tabber-relations', _('Relations'), false, true));
+                               $count=db_numrows($ah->getRelations());
+                               $nbr = $count? ' ('.$count.')' : '';
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-relations', _('Relations').$nbr, false, true));
+                       }
+                       if (forge_get_config('use_artefacts_dependencies')) {
+                               $tabTitle = _('Children');
+                               $nbChildren = $ah->hasChildren();
+                               if ($nbChildren) {
+                                       $tabTitle .= ' ('.$nbChildren.')';
+                               }
+                               $elementsLi[] = array('content' => 
util_make_link('#tabber-children', $tabTitle, false, true));
                        }
                        if (forge_get_config('use_object_associations')) {
                                $tabTitle = _('Associations');
@@ -153,7 +167,12 @@ class Widget_TrackerComment extends Widget {
                if ($func == 'detail') {
                        $tabberContent .= html_e('div', array('id' => 
'tabber-changes', 'class' => 'tabbertab'),
                                                $ah->showHistory());
-                       $tabberContent .= $ah->showRelations();
+                       $tabberContent .= html_e('div', array('id' => 
'tabber-relations', 'class' => 'tabbertab'),
+                                               $ah->showRelations());
+                       if (forge_get_config('use_artefacts_dependencies')) {
+                               $tabberContent .= html_e('div', array('id' => 
'tabber-children', 'class' => 'tabbertab'),
+                                               $ah->showChildren());
+                       }
                        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')) 
{
diff --git a/src/db/20170502-tracker-parent-artifact.sql 
b/src/db/20170502-tracker-parent-artifact.sql
new file mode 100644
index 0000000..96e327c
--- /dev/null
+++ b/src/db/20170502-tracker-parent-artifact.sql
@@ -0,0 +1,3 @@
+ALTER TABLE artifact_extra_field_list
+   ADD COLUMN aggregation_rule integer NOT NULL DEFAULT 0,
+   ADD COLUMN distribution_rule integer NOT NULL DEFAULT 0;
\ No newline at end of file
diff --git a/src/www/include/Layout.class.php b/src/www/include/Layout.class.php
index 694d86d..45b5e3d 100644
--- a/src/www/include/Layout.class.php
+++ b/src/www/include/Layout.class.php
@@ -1013,6 +1013,10 @@ abstract class Layout extends FFError {
                return $this->getPicto('ic/edit-file.png', $title, $alt, 20, 
20, $otherAttr);
        }
 
+       function getEditFieldPic($title = '', $alt = '', $otherAttr = array()) {
+               return $this->getPicto('ic/forum_edit.png', $title, $alt, 20, 
20, $otherAttr);
+       }
+
        function getNewPic($title = '', $alt = '', $otherAttr = array()) {
                return $this->getPicto('ic/add.png', $title, $alt, 20, 20, 
$otherAttr);
        }
diff --git a/src/www/themes/funky-wOw/css/theme.css 
b/src/www/themes/funky-wOw/css/theme.css
index 48778d2..f1ae5ff 100644
--- a/src/www/themes/funky-wOw/css/theme.css
+++ b/src/www/themes/funky-wOw/css/theme.css
@@ -131,3 +131,6 @@ input, select {
        vertical-align: middle;
 }
 
+.artifact_closed, .artifact_closed:hover {
+       text-decoration:line-through;
+}
\ No newline at end of file
diff --git a/src/www/themes/funky/css/theme.css 
b/src/www/themes/funky/css/theme.css
index a7de379..89bda99 100644
--- a/src/www/themes/funky/css/theme.css
+++ b/src/www/themes/funky/css/theme.css
@@ -800,3 +800,7 @@ footer img {
 input, select {
        vertical-align: middle;
 }
+
+.artifact_closed, .artifact_closed:hover {
+       text-decoration:line-through;
+}
\ No newline at end of file

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

Summary of changes:
 src/common/tracker/Artifact.class.php              | 94 ++++++++++++++++++++--
 src/common/tracker/ArtifactExtraField.class.php    | 85 ++++++++++++++++---
 src/common/tracker/actions/admin-updates.php       |  4 +-
 src/common/tracker/actions/detail.php              | 33 ++++++--
 src/common/tracker/actions/effort_units.php        |  1 -
 src/common/tracker/actions/mod-limited.php         | 33 ++++++--
 src/common/tracker/actions/mod.php                 | 37 +++++++--
 src/common/tracker/include/ArtifactHtml.class.php  | 71 +++++++++-------
 .../tracker/include/ArtifactTypeHtml.class.php     | 38 ++++++++-
 src/common/tracker/views/form-addextrafield.php    | 16 +++-
 src/common/tracker/views/form-editformula.php      |  9 +--
 src/common/tracker/views/form-updateextrafield.php | 15 ++++
 src/common/widget/Widget_TrackerComment.class.php  | 27 ++++++-
 src/db/20170502-tracker-parent-artifact.sql        |  3 +
 src/www/include/Layout.class.php                   |  4 +
 src/www/themes/funky-wOw/css/theme.css             |  3 +
 src/www/themes/funky/css/theme.css                 |  4 +
 17 files changed, 397 insertions(+), 80 deletions(-)
 create mode 100644 src/db/20170502-tracker-parent-artifact.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