From f4b8b4cae3f874c5c4a7c8917bdc3e04572b1e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Espi=C3=A9?= Date: Fri, 6 Apr 2018 08:53:30 +0000 Subject: [PATCH] =?UTF-8?q?N=C2=B01161=20-=20Dashlet=20Group=20By=20suppor?= =?UTF-8?q?ts=20sum,=20average,=20min=20and=20max.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SVN:trunk[5623] --- application/dashlet.class.inc.php | 145 +++++++++++++++++++++++-- application/displayblock.class.inc.php | 109 ++++++++++++++++--- dictionaries/en.dictionary.itop.ui.php | 21 ++++ dictionaries/fr.dictionary.itop.ui.php | 22 +++- js/dashlet.js | 21 ++-- pages/ajax.render.php | 2 +- 6 files changed, 286 insertions(+), 34 deletions(-) diff --git a/application/dashlet.class.inc.php b/application/dashlet.class.inc.php index 2c21628aa..0464d58c7 100644 --- a/application/dashlet.class.inc.php +++ b/application/dashlet.class.inc.php @@ -700,12 +700,21 @@ abstract class DashletGroupBy extends Dashlet $this->aProperties['query'] = 'SELECT Contact'; $this->aProperties['group_by'] = 'status'; $this->aProperties['style'] = 'table'; + $this->aProperties['agregation_function'] = 'count'; + $this->aProperties['agregation_attribute'] = ''; + $this->aProperties['limit'] = ''; + $this->aProperties['order_direction'] = 'desc'; } protected $sGroupByLabel = null; protected $sGroupByExpr = null; protected $sGroupByAttCode = null; protected $sFunction = null; + protected $sAgregationFunction = null; + protected $sAgregationAttribute = null; + protected $sLimit = null; + protected $sOrderDirection = null; + protected $sClass = null; /** * Compute Grouping @@ -716,22 +725,27 @@ abstract class DashletGroupBy extends Dashlet $this->sGroupByLabel = null; $this->sGroupByAttCode = null; $this->sFunction = null; + $this->sClass = null; $sQuery = $this->aProperties['query']; $sGroupBy = $this->aProperties['group_by']; - $sStyle = $this->aProperties['style']; + + $this->sAgregationFunction = $this->aProperties['agregation_function']; + $this->sAgregationAttribute = $this->aProperties['agregation_attribute']; + $this->sLimit = $this->aProperties['limit']; + $this->sOrderDirection = $this->aProperties['order_direction']; // First perform the query - if the OQL is not ok, it will generate an exception : no need to go further try { $oQuery = $this->oModelReflection->GetQuery($sQuery); - $sClass = $oQuery->GetClass(); + $this->sClass = $oQuery->GetClass(); $sClassAlias = $oQuery->GetClassAlias(); } catch(Exception $e) { // Invalid query, let the user edit the dashlet/dashboard anyhow - $sClass = ''; + $this->sClass = null; $sClassAlias = ''; } // Check groupby... it can be wrong at this stage @@ -745,9 +759,9 @@ abstract class DashletGroupBy extends Dashlet $this->sGroupByAttCode = $sGroupBy; $this->sFunction = null; } - if (($sClass != '') && $this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode)) + if ((!is_null($this->sClass)) && $this->oModelReflection->IsValidAttCode($this->sClass, $this->sGroupByAttCode)) { - $sAttLabel = $this->oModelReflection->GetLabel($sClass, $this->sGroupByAttCode); + $sAttLabel = $this->oModelReflection->GetLabel($this->sClass, $this->sGroupByAttCode); if (!is_null($this->sFunction)) { switch($this->sFunction) @@ -793,7 +807,6 @@ abstract class DashletGroupBy extends Dashlet { $sTitle = $this->aProperties['title']; $sQuery = $this->aProperties['query']; - $sGroupBy = $this->aProperties['group_by']; $sStyle = $this->aProperties['style']; // First perform the query - if the OQL is not ok, it will generate an exception : no need to go further @@ -801,7 +814,6 @@ abstract class DashletGroupBy extends Dashlet $oFilter->SetShowObsoleteData(utils::ShowObsoleteData()); $sClass = $oFilter->GetClass(); - $sClassAlias = $oFilter->GetClassAlias(); if (!$this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode)) { @@ -818,6 +830,10 @@ abstract class DashletGroupBy extends Dashlet 'chart_title' => $sTitle, 'group_by' => $this->sGroupByExpr, 'group_by_label' => $this->sGroupByLabel, + 'agregation_function' => $this->sAgregationFunction, + 'agregation_attribute' => $this->sAgregationAttribute, + 'limit' => $this->sLimit, + 'order_direction' => $this->sOrderDirection, ); $sHtmlTitle = ''; // done in the itop block break; @@ -829,6 +845,10 @@ abstract class DashletGroupBy extends Dashlet 'chart_title' => $sTitle, 'group_by' => $this->sGroupByExpr, 'group_by_label' => $this->sGroupByLabel, + 'agregation_function' => $this->sAgregationFunction, + 'agregation_attribute' => $this->sAgregationAttribute, + 'limit' => $this->sLimit, + 'order_direction' => $this->sOrderDirection, ); $sHtmlTitle = ''; // done in the itop block break; @@ -840,6 +860,10 @@ abstract class DashletGroupBy extends Dashlet $aExtraParams = array( 'group_by' => $this->sGroupByExpr, 'group_by_label' => $this->sGroupByLabel, + 'agregation_function' => $this->sAgregationFunction, + 'agregation_attribute' => $this->sAgregationAttribute, + 'limit' => $this->sLimit, + 'order_direction' => $this->sOrderDirection, ); break; } @@ -966,6 +990,10 @@ abstract class DashletGroupBy extends Dashlet return $aGroupBy; } + /** + * @param DesignerForm $oForm + * @throws DictExceptionMissingString + */ public function GetPropertiesFields(DesignerForm $oForm) { $oField = new DesignerTextField('title', Dict::S('UI:DashletGroupBy:Prop-Title'), $this->aProperties['title']); @@ -1001,6 +1029,100 @@ abstract class DashletGroupBy extends Dashlet $oField->SetMandatory(); $oField->SetAllowedValues($aStyles); $oForm->AddField($oField); + + $aFunctionAttributes = $this->GetNumericAttributes($this->aProperties['query']); + $aFunctions = $this->GetAllowedFunctions($aFunctionAttributes); + $oSelectorField = new DesignerFormSelectorField('agregation_function', Dict::S('UI:DashletGroupBy:Prop-Function'), $this->aProperties['agregation_function']); + $oForm->AddField($oSelectorField); + $oSelectorField->SetMandatory(); + // Count sub-menu + $oSubForm = new DesignerForm(); + $oSelectorField->AddSubForm($oSubForm, Dict::S('UI:GroupBy:count'), 'count'); + foreach($aFunctions as $sFct => $sLabel) + { + $oSubForm = new DesignerForm(); + $oField = new DesignerComboField('agregation_attribute', Dict::S('UI:DashletGroupBy:Prop-FunctionAttribute'), $this->aProperties['agregation_attribute']); + $oField->SetMandatory(); + $oField->SetAllowedValues($aFunctionAttributes); + $oSubForm->AddField($oField); + $oSelectorField->AddSubForm($oSubForm, $sLabel, $sFct); + } + + $aOrderDirections = array( + 'asc' => Dict::S('UI:DashletGroupBy:Order:asc'), + 'desc' => Dict::S('UI:DashletGroupBy:Order:desc'), + ); + $oField = new DesignerComboField('order_direction', Dict::S('UI:DashletGroupBy:Prop-OrderDirection'), $this->aProperties['order_direction']); + $oField->SetMandatory(); + $oField->SetAllowedValues($aOrderDirections); + $oForm->AddField($oField); + + $oField = new DesignerIntegerField('limit', Dict::S('UI:DashletGroupBy:Prop-Limit'), $this->aProperties['limit']); + $oForm->AddField($oField); + + } + + /** + * @return array + * @throws DictExceptionMissingString + */ + protected function GetOrderBy() + { + if (is_null($this->sClass)) + { + return array(); + } + return array( + $this->aProperties['group_by'] => $this->oModelReflection->GetLabel($this->sClass, $this->aProperties['group_by']), + '_itop_'.$this->aProperties['agregation_function'].'_' => Dict::S('UI:GroupBy:'.$this->aProperties['agregation_function'])); + } + + /** + * @return array + * @throws DictExceptionMissingString + */ + protected function GetAllowedFunctions($aFunctionAttributes) + { + $aFunctions = array(); + + if (!empty($aFunctionAttributes) || is_null($this->sClass)) + { + $aFunctions['sum'] = Dict::S('UI:GroupBy:sum'); + $aFunctions['avg'] = Dict::S('UI:GroupBy:avg'); + $aFunctions['min'] = Dict::S('UI:GroupBy:min'); + $aFunctions['max'] = Dict::S('UI:GroupBy:max'); + } + + return $aFunctions; + } + + /** + * @return array + */ + protected function GetNumericAttributes($sOql) + { + $aFunctionAttributes = array(); + $oQuery = $this->oModelReflection->GetQuery($sOql); + $sClass = $oQuery->GetClass(); + if (is_null($sClass)) + { + return $aFunctionAttributes; + } + foreach($this->oModelReflection->ListAttributes($sClass) as $sAttCode => $sAttType) + { + switch ($sAttType) + { + case 'AttributeDecimal': + case 'AttributeDuration': + case 'AttributeInteger': + case 'AttributePercentage': + $sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode); + $aFunctionAttributes[$sAttCode] = $sLabel; + break; + } + } + + return $aFunctionAttributes; } public function Update($aValues, $aUpdatedFields) @@ -1052,6 +1174,15 @@ abstract class DashletGroupBy extends Dashlet $oDashlet->bRedrawNeeded = true; $oDashlet->bFormRedrawNeeded = true; } + if (in_array('group_by', $aUpdatedFields) || in_array('agregation_attribute', $aUpdatedFields) || in_array('order_direction', $aUpdatedFields) || in_array('limit', $aUpdatedFields)) + { + $oDashlet->bRedrawNeeded = true; + } + if (in_array('agregation_function', $aUpdatedFields)) + { + $oDashlet->bRedrawNeeded = true; + $oDashlet->bFormRedrawNeeded = true; + } return $oDashlet; } diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index c23abd980..1574966de 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -285,7 +285,19 @@ class DisplayBlock } $oPage->add($this->GetRenderContent($oPage, $aExtraParams, $sId)); } - + + /** + * @param WebPage $oPage + * @param array $aExtraParams + * @param $sId + * @return string + * @throws ApplicationException + * @throws CoreException + * @throws CoreWarning + * @throws DictExceptionMissingString + * @throws MySQLException + * @throws Exception + */ public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId) { $sHtml = ''; @@ -400,6 +412,7 @@ class DisplayBlock case 'count': if (isset($aExtraParams['group_by'])) { + $sAlias = $this->m_oFilter->GetClassAlias(); if (isset($aExtraParams['group_by_label'])) { $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']); @@ -408,7 +421,6 @@ class DisplayBlock else { // Backward compatibility: group_by is simply a field id - $sAlias = $this->m_oFilter->GetClassAlias(); $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias); $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']); } @@ -430,7 +442,42 @@ class DisplayBlock $aGroupBy = array(); $aGroupBy['grouped_by_1'] = $oGroupByExp; - $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true); + $aQueryParams = array(); + if (isset($aExtraParams['query_params'])) + { + $aQueryParams = $aExtraParams['query_params']; + } + $aFunctions = array(); + $aOrderBy = array(); + $sAgregationFunction = 'count'; + $sFctVar = '_itop_count_'; + $sAgregationAttr = ''; + if (isset($aExtraParams['agregation_function']) && !empty($aExtraParams['agregation_attribute'])) + { + $sAgregationFunction = $aExtraParams['agregation_function']; + $sAgregationAttr = $aExtraParams['agregation_attribute']; + $oAttrExpr = Expression::FromOQL('`'.$sAlias.'`.`'.$sAgregationAttr.'`'); + $oFctExpr = new FunctionExpression(strtoupper($sAgregationFunction), array($oAttrExpr)); + $sFctVar = '_itop_'.$sAgregationFunction.'_'; + $aFunctions = array($sFctVar => $oFctExpr); + } + if (!empty($sAgregationAttr)) + { + $sClass = $this->m_oFilter->GetClass(); + $sAgregationAttr = MetaModel::GetLabel($sClass, $sAgregationAttr); + } + $iLimit = 0; + if (isset($aExtraParams['limit'])) + { + $iLimit = intval($aExtraParams['limit']); + } + if (isset($aExtraParams['order_direction'])) + { + $aOrderBy = array($sFctVar => ($aExtraParams['order_direction'] === 'asc')); + } + + $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true, $aFunctions, $aOrderBy, $iLimit); + $aRes = CMDBSource::QueryToArray($sSql); $aGroupBy = array(); @@ -443,7 +490,7 @@ class DisplayBlock $aValues[$iRow] = $sValue; $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue); $aLabels[$iRow] = $sHtmlValue; - $aGroupBy[$iRow] = (int) $aRow['_itop_count_']; + $aGroupBy[$iRow] = (int) $aRow[$sFctVar]; $iTotalCount += $aRow['_itop_count_']; } @@ -459,12 +506,12 @@ class DisplayBlock $oSubsetSearch->AddConditionExpression($oCondition); $sFilter = urlencode($oSubsetSearch->serialize()); - $aData[] = array ( 'group' => $aLabels[$iRow], + $aData[] = array ('group' => $aLabels[$iRow], 'value' => "$iCount"); // TO DO: add the context information } $aAttribs =array( 'group' => array('label' => $sGroupByLabel, 'description' => ''), - 'value' => array('label'=> Dict::S('UI:GroupBy:Count'), 'description' => Dict::S('UI:GroupBy:Count+')) + 'value' => array('label'=> Dict::S('UI:GroupBy:'.$sAgregationFunction), 'description' => Dict::Format('UI:GroupBy:'.$sAgregationFunction.'+', $sAgregationAttr)) ); $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection'; $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount)); @@ -924,18 +971,21 @@ class DisplayBlock $sFilter = $this->m_oFilter->serialize(); $oContext = new ApplicationContext(); $sContextParam = $oContext->GetForLink(); + $sAgregationFunction = isset($aExtraParams['agregation_function']) ? $aExtraParams['agregation_function'] : ''; + $sAgregationAttr = isset($aExtraParams['agregation_attribute']) ? $aExtraParams['agregation_attribute'] : ''; + $sLimit = isset($aExtraParams['limit']) ? $aExtraParams['limit'] : ''; + $sOrderBy = isset($aExtraParams['order_by']) ? $aExtraParams['order_by'] : ''; + $sOrderDirection = isset($aExtraParams['order_direction']) ? $aExtraParams['order_direction'] : ''; if (isset($aExtraParams['group_by_label'])) { - $sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart¶ms[group_by]=$sGroupBy{$sGroupByExpr}¶ms[group_by_label]={$aExtraParams['group_by_label']}¶ms[chart_type]=$sChartType¶ms[currentId]=$sId{$iChartCounter}&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam); + $sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart¶ms[group_by]=$sGroupBy{$sGroupByExpr}¶ms[group_by_label]={$aExtraParams['group_by_label']}¶ms[chart_type]=$sChartType¶ms[currentId]=$sId{$iChartCounter}¶ms[order_direction]=$sOrderDirection¶ms[order_by]=$sOrderBy¶ms[limit]=$sLimit¶ms[agregation_function]=$sAgregationFunction¶ms[agregation_attribute]=$sAgregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam); } else { - $sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart¶ms[group_by]=$sGroupBy{$sGroupByExpr}¶ms[chart_type]=$sChartType¶ms[currentId]=$sId{$iChartCounter}&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam); + $sUrl = json_encode(utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=chart¶ms[group_by]=$sGroupBy{$sGroupByExpr}¶ms[chart_type]=$sChartType¶ms[currentId]=$sId{$iChartCounter}¶ms[order_direction]=$sOrderDirection¶ms[order_by]=$sOrderBy¶ms[limit]=$sLimit¶ms[agregation_function]=$sAgregationFunction¶ms[agregation_attribute]=$sAgregationAttr&id=$sId{$iChartCounter}&filter=".urlencode($sFilter).'&'.$sContextParam); } - - $sType = ($sChartType == 'pie') ? 'pie' : 'bar'; - + $oPage->add_ready_script( <<m_oFilter->GetClassAlias(); if (isset($aExtraParams['group_by_label'])) { $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']); - $sGroupByLabel = $aExtraParams['group_by_label']; } else { // Backward compatibility: group_by is simply a field id - $sAlias = $this->m_oFilter->GetClassAlias(); $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias); - $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']); } $aGroupBy = array(); $aGroupBy['grouped_by_1'] = $oGroupByExp; - $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true); + $aQueryParams = array(); + if (isset($aExtraParams['query_params'])) + { + $aQueryParams = $aExtraParams['query_params']; + } + $aFunctions = array(); + $aOrderBy = array(); + $sFctVar = '_itop_count_'; + if (isset($aExtraParams['agregation_function']) && !empty($aExtraParams['agregation_attribute'])) + { + $sAgregationFunction = $aExtraParams['agregation_function']; + $sAgregationAttr = $aExtraParams['agregation_attribute']; + $oAttrExpr = Expression::FromOQL('`'.$sAlias.'`.`'.$sAgregationAttr.'`'); + $oFctExpr = new FunctionExpression(strtoupper($sAgregationFunction), array($oAttrExpr)); + $sFctVar = '_itop_'.$sAgregationFunction.'_'; + $aFunctions = array($sFctVar => $oFctExpr); + } + $iLimit = 0; + if (isset($aExtraParams['limit'])) + { + $iLimit = intval($aExtraParams['limit']); + } + if (isset($aExtraParams['order_direction'])) + { + $aOrderBy = array($sFctVar => ($aExtraParams['order_direction'] === 'asc')); + } + + $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true, $aFunctions, $aOrderBy, $iLimit); $aRes = CMDBSource::QueryToArray($sSql); $oContext = new ApplicationContext(); $sContextParam = $oContext->GetForLink(); @@ -980,9 +1055,9 @@ EOF { $sValue = $aRow['grouped_by_1']; $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue); - $aGroupBy[(int)$iRow] = (int) $aRow['_itop_count_']; + $aGroupBy[(int)$iRow] = (int) $aRow[$sFctVar]; $iTotalCount += $aRow['_itop_count_']; - $aValues[] = array('label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'), 'label_html' => $sHtmlValue, 'value' => (int) $aRow['_itop_count_']); + $aValues[] = array('label' => html_entity_decode(strip_tags($sHtmlValue), ENT_QUOTES, 'UTF-8'), 'label_html' => $sHtmlValue, 'value' => (int) $aRow[$sFctVar]); // Build the search for this subset $oSubsetSearch = $this->m_oFilter->DeepClone(); diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php index 236abed14..7a846865a 100644 --- a/dictionaries/en.dictionary.itop.ui.php +++ b/dictionaries/en.dictionary.itop.ui.php @@ -1217,6 +1217,27 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:DashletGroupByTable:Label' => 'Group By (table)', 'UI:DashletGroupByTable:Description' => 'List (Grouped by a field)', + // New in 2.5 + 'UI:DashletGroupBy:Prop-Function' => 'Agregation function', + 'UI:DashletGroupBy:Prop-FunctionAttribute' => 'Function attribute', + 'UI:DashletGroupBy:Prop-OrderDirection' => 'Direction', + 'UI:DashletGroupBy:Prop-Limit' => 'Limit', + + 'UI:DashletGroupBy:Order:asc' => 'Ascending', + 'UI:DashletGroupBy:Order:desc' => 'Descending', + + 'UI:GroupBy:count' => 'Count', + 'UI:GroupBy:count+' => 'Number of elements', + 'UI:GroupBy:sum' => 'Sum', + 'UI:GroupBy:sum+' => 'Sum of %1$s', + 'UI:GroupBy:avg' => 'Average', + 'UI:GroupBy:avg+' => 'Average of %1$s', + 'UI:GroupBy:min' => 'Minimum', + 'UI:GroupBy:min+' => 'Minimum of %1$s', + 'UI:GroupBy:max' => 'Maximum', + 'UI:GroupBy:max+' => 'Maximum of %1$s', + // --- + 'UI:DashletHeaderStatic:Label' => 'Header', 'UI:DashletHeaderStatic:Description' => 'Displays an horizontal separator', 'UI:DashletHeaderStatic:Prop-Title' => 'Title', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 53ce55c32..8f94ee4c3 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -160,7 +160,6 @@ Dict::Add('FR FR', 'French', 'Français', array( 'Class:User/Attribute:status+' => 'Est-ce que ce compte utilisateur est actif, ou non?', 'Class:User/Attribute:status/Value:enabled' => 'Actif', 'Class:User/Attribute:status/Value:disabled' => 'Désactivé', - 'Class:User/Attribute:status' => 'Etat', 'Class:User/Error:LoginMustBeUnique' => 'Le login doit être unique - "%1s" est déjà utilisé.', 'Class:User/Error:AtLeastOneProfileIsNeeded' => 'L\'utilisateur doit avoir au moins un profil.', 'Class:UserInternal' => 'Utilisateur interne', @@ -1054,6 +1053,27 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'UI:DashletGroupByTable:Label' => 'Table', 'UI:DashletGroupByTable:Description' => 'Table', + // New in 2.5 + 'UI:DashletGroupBy:Prop-Function' => 'Fonction d\'agregation', + 'UI:DashletGroupBy:Prop-FunctionAttribute' => 'Attribut', + 'UI:DashletGroupBy:Prop-OrderDirection' => 'Type de tri', + 'UI:DashletGroupBy:Prop-Limit' => 'Limite', + + 'UI:DashletGroupBy:Order:asc' => 'Croissant', + 'UI:DashletGroupBy:Order:desc' => 'Décroissant', + + 'UI:GroupBy:count' => 'Nombre', + 'UI:GroupBy:count+' => 'Nombre d\'éléments', + 'UI:GroupBy:sum' => 'Somme', + 'UI:GroupBy:sum+' => 'Somme : %1$s', + 'UI:GroupBy:avg' => 'Moyenne', + 'UI:GroupBy:avg+' => 'Moyenne : %1$s', + 'UI:GroupBy:min' => 'Minimum', + 'UI:GroupBy:min+' => 'Minimum : %1$s', + 'UI:GroupBy:max' => 'Maximum', + 'UI:GroupBy:max+' => 'Maximum : %1$s', + // --- + 'UI:DashletHeaderStatic:Label' => 'En-tête', 'UI:DashletHeaderStatic:Description' => 'En-tête présenté comme une barre horizontale', 'UI:DashletHeaderStatic:Prop-Title' => 'Titre', diff --git a/js/dashlet.js b/js/dashlet.js index 7794baf06..2112d4a20 100644 --- a/js/dashlet.js +++ b/js/dashlet.js @@ -102,14 +102,19 @@ $(function() { var oParams = {}; var oProperties = $('#dashlet_properties_'+this.options.dashlet_id); - oProperties.find(':itop-property_field').each(function(){ - var oWidget = $(this).data('itopProperty_field'); - if (oWidget) - { - var oVal = oWidget._get_committed_value(); - oParams[oVal.name] = oVal.value; - } - }); + oProperties.find('.itop-property-field').each(function(){ + var oWidget = $(this).data('itopProperty_field'); + if (oWidget == undefined) + { + oWidget = $(this).data('itopSelector_property_field'); + } + if (oWidget && $(this).is(':visible')) + { + var oVal = oWidget._get_committed_value(); + oParams[oVal.name] = oVal.value; + } + }); + oParams.dashlet_id = this.options.dashlet_id; oParams.dashlet_class = this.options.dashlet_class; return oParams; diff --git a/pages/ajax.render.php b/pages/ajax.render.php index c396b1488..7c7f7bf94 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -965,7 +965,7 @@ try foreach($aUpdatedProperties as $sProp) { $sDecodedProp = str_replace('attr_', '', $sProp); // Remove the attr_ prefix - $aCurrentValues[$sDecodedProp] = $aPreviousValues[$sProp]; // Set the previous value + $aCurrentValues[$sDecodedProp] = (isset($aPreviousValues[$sProp]) ? $aPreviousValues[$sProp] : ''); // Set the previous value $aUpdatedDecoded[] = $sDecodedProp; }