Dashboards - Finalized the implementation (inc. translation in french) - still some known issues

SVN:trunk[2195]
This commit is contained in:
Romain Quetiez
2012-09-20 15:56:15 +00:00
parent 77129d010e
commit dac73c1669
15 changed files with 463 additions and 544 deletions

View File

@@ -178,10 +178,10 @@ abstract class Dashboard
public function RenderProperties($oPage)
{
// menu to pick a layout and edit other properties of the dashboard
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">Dashboard Properties</div>');
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Properties').'</div>');
$sUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->add('<div style="text-align:center">Layout:</div>');
$oPage->add('<div style="text-align:center">'.Dict::S('UI:DashboardEdit:Layout').'</div>');
$oPage->add('<div id="select_layout" style="text-align:center">');
foreach( get_declared_classes() as $sLayoutClass)
{
@@ -200,7 +200,7 @@ abstract class Dashboard
$oPage->add('</div>');
$oForm = new DesignerForm();
$oField = new DesignerLongTextField('dashboard_title', 'Title', $this->sTitle);
$oField = new DesignerLongTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
$oForm->AddField($oField);
$this->SetFormParams($oForm);
$oForm->RenderAsPropertySheet($oPage);
@@ -226,7 +226,7 @@ EOF
public function RenderDashletsSelection($oPage)
{
// Toolbox/palette to drag and drop dashlets
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">Available Dashlets</div>');
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:Dashlets').'</div>');
$sUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->add('<div id="select_dashlet" style="text-align:center">');
@@ -258,7 +258,7 @@ EOF
public function RenderDashletsProperties($oPage)
{
// Toolbox/palette to edit the properties of each dashlet
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">Dashlet Properties</div>');
$oPage->add('<div class="ui-widget-content ui-corner-all"><div class="ui-widget-header ui-corner-all" style="text-align:center; padding: 2px;">'.Dict::S('UI:DashboardEdit:DashletProperties').'</div>');
$oPage->add('<div id="dashlet_properties" style="text-align:center">');
foreach($this->aCells as $aCell)
@@ -284,7 +284,15 @@ EOF
protected function GetNewDashletId()
{
return 999;
$iNewId = 0;
foreach($this->aCells as $aDashlets)
{
foreach($aDashlets as $oDashlet)
{
$iNewId = max($iNewId, (int)$oDashlet->GetID());
}
}
return $iNewId + 1;
}
abstract protected function SetFormParams($oForm);
@@ -357,10 +365,11 @@ class RuntimeDashboard extends Dashboard
if (!$bEditMode)
{
$sEditMenu = "<td><span id=\"DashboardMenu\"><ul><li><img src=\"../images/edit.png\"><ul>";
$sEditMenu .= "<li><a href=\"#\" onclick=\"return EditDashboard('{$this->sId}')\">Edit This Page...</a></li>";
$sEditMenu .= "<li><a href=\"#\" onclick=\"return EditDashboard('{$this->sId}')\">".Dict::S('UI:Dashboard:Edit')."</a></li>";
if ($this->bCustomized)
{
$sEditMenu .= "<li><a href=\"#\" onclick=\"return RevertDashboard('{$this->sId}')\">Revert To Original Version</a></li>";
$sEditMenu .= "<li><a href=\"#\" onclick=\"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}'); else return false;\">".Dict::S('UI:Dashboard:Revert')."</a></li>";
}
$sEditMenu .= "</ul></li></ul></span></td>";
$sEditMenu = addslashes($sEditMenu);
@@ -413,8 +422,8 @@ EOF
$oPage->add('<div id="event_bus"/>'); // For exchanging messages between the panes, same as in the designer
$oPage->add('</div>');
$sDialogTitle = 'Dashboard Editor';
$sOkButtonLabel = Dict::S('UI:Button:Ok');
$sDialogTitle = Dict::S('UI:DashboardEdit:Title');
$sOkButtonLabel = Dict::S('UI:Button:Save');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$sId = addslashes($this->sId);
@@ -472,11 +481,13 @@ $('#event_bus').bind('dashlet-selected', function(event, data){
});
dashboard_prop_size = GetUserPreference('dashboard_prop_size', 300);
dashboard_prop_size = GetUserPreference('dashboard_prop_size', 350);
$('#dashboard_editor').layout({
east: {
minSize: 150,
minSize: 200,
size: dashboard_prop_size,
togglerLength_open: 0,
togglerLength_closed: 0,
onresize_end: function(name, elt, state, options, layout)
{
if (state.isSliding == false)
@@ -486,13 +497,12 @@ $('#dashboard_editor').layout({
},
}
});
EOF
);
$oPage->add_ready_script("");
}
public static function GetDashletCreationForm($sOQL)
public static function GetDashletCreationForm($sOQL = null)
{
$oForm = new DesignerForm();
@@ -502,15 +512,26 @@ EOF
foreach($aAllMenus as $idx => $aMenu)
{
$oMenu = $aMenu['node'];
$sParentId = $aMenu['parent'];
if ($oMenu instanceof DashboardMenuNode)
{
$aAllowedDashboards[$oMenu->GetMenuId()] = Dict::S($oMenu->GetMenuId());
$sMenuLabel = $oMenu->GetTitle();
$sParentLabel = Dict::S('Menu:'.$sParentId);
if ($sParentLabel != $sMenuLabel)
{
$aAllowedDashboards[$oMenu->GetMenuId()] = $sParentLabel.' - '.$sMenuLabel;
}
else
{
$aAllowedDashboards[$oMenu->GetMenuId()] = $sMenuLabel;
}
}
}
asort($aAllowedDashboards);
$aKeys = array_keys($aAllowedDashboards); // Select the first one by default
$sDefaultDashboard = $aKeys[0];
$oField = new DesignerComboField('menu_id', 'Dashboard', $sDefaultDashboard);
$oField = new DesignerComboField('menu_id', Dict::S('UI:DashletCreation:Dashboard'), $sDefaultDashboard);
$oField->SetAllowedValues($aAllowedDashboards);
$oField->SetMandatory(true);
$oForm->AddField($oField);
@@ -518,7 +539,7 @@ EOF
// Get the list of possible dashlets that support a creation from
// an OQL
$aDashlets = array();
foreach( get_declared_classes() as $sDashletClass)
foreach(get_declared_classes() as $sDashletClass)
{
if (is_subclass_of($sDashletClass, 'Dashlet'))
{
@@ -537,7 +558,7 @@ EOF
}
}
$oSelectorField = new DesignerFormSelectorField('dashlet_class', 'Dashlet Type', '');
$oSelectorField = new DesignerFormSelectorField('dashlet_class', Dict::S('UI:DashletCreation:DashletType'), '');
$oForm->AddField($oSelectorField);
foreach($aDashlets as $sDashletClass => $aDashletInfo)
{
@@ -547,7 +568,7 @@ EOF
$oSelectorField->AddSubForm($oSubForm, $aDashletInfo['label'], $aDashletInfo['class']);
}
$oField = new DesignerBooleanField('open_editor', 'Edit the Dashboard', true);
$oField = new DesignerBooleanField('open_editor', Dict::S('UI:DashletCreation:EditNow'), true);
$oForm->AddField($oField);
return $oForm;
@@ -558,11 +579,11 @@ EOF
$oPage->add('<div id="dashlet_creation_dlg">');
$oForm = self::GetDashletCreationForm($sOQL);
$oForm->Render($oPage);
$oPage->add('</div>');
$sDialogTitle = 'Create a new Dashlet';
$sDialogTitle = Dict::S('UI:DashletCreation:Title');
$sOkButtonLabel = Dict::S('UI:Button:Ok');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');

View File

@@ -145,13 +145,21 @@ abstract class Dashlet
if ($bEditMode)
{
$oPage->add('<div class="dashlet-content">');
$oPage->add('<h2>Unknown Class: '.$e->GetWrongWord().', did you mean '.OqlException::FindClosestString($e->GetWrongWord(), $e->GetSuggestions()).'?</h2>'); //TODO localize and
$oPage->add('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
$oPage->add('</div>');
}
}
catch(OqlException $e)
{
$oPage->add('<div class="dashlet-content">');
$oPage->p($e->GetUserFriendlyDescription());
$oPage->add('</div>');
}
catch(Exception $e)
{
$oPage->add('<div class="dashlet-content">');
$oPage->p($e->getMessage());
$oPage->add('</div>');
}
if ($bEnclosingDiv)
@@ -248,7 +256,7 @@ EOF
return false;
}
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL)
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL = null)
{
// Default: do nothing since it's not supported
}
@@ -285,34 +293,35 @@ class DashletEmptyCell extends Dashlet
}
}
class DashletRichText extends Dashlet
class DashletPlainText extends Dashlet
{
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['text'] = "<h1>Lorem ipsum</h1>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper.</p><p>Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit. Ut velit mauris, egestas sed, gravida nec, ornare ut, mi. Aenean ut orci vel massa suscipit pulvinar. Nulla sollicitudin. Fusce varius, ligula non tempus aliquam, nunc turpis ullamcorper nibh, in tempus sapien eros vitae ligula. Pellentesque rhoncus nunc et augue.</p><p>Integer id felis. Curabitur aliquet pellentesque diam. Integer quis metus vitae elit lobortis egestas. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi vel erat non mauris convallis vehicula. Nulla et sapien. Integer tortor tellus, aliquam faucibus, convallis id, congue eu, quam. Mauris ullamcorper felis vitae erat. Proin feugiat, augue non elementum posuere, metus purus iaculis lectus, et tristique ligula justo vitae magna. Aliquam convallis sollicitudin purus. Praesent aliquam, enim at fermentum mollis, ligula massa adipiscing nisl, ac euismod nibh nisl eu lectus. Fusce vulputate sem at sapien. Vivamus leo. Aliquam euismod libero eu enim. Nulla nec felis sed leo placerat imperdiet.</p><p>Aenean suscipit nulla in justo. Suspendisse cursus rutrum augue. Nulla tincidunt tincidunt mi. Curabitur iaculis, lorem vel rhoncus faucibus, felis magna fermentum augue, et ultricies lacus lorem varius purus. Curabitur eu amet.</p>";
$this->aProperties['text'] = Dict::S('UI:DashletPlainText:Prop-Text:Default');
}
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$sText = $this->aProperties['text'];
$sText = htmlentities($this->aProperties['text'], ENT_QUOTES, 'UTF-8');
$sId = 'richtext_'.($bEditMode? 'edit_' : '').$this->sId;
$sId = 'plaintext_'.($bEditMode? 'edit_' : '').$this->sId;
$oPage->add('<div id='.$sId.'" class="dashlet-content">'.$sText.'</div>');
}
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerLongTextField('text', 'Text', $this->aProperties['text']);
$oField = new DesignerLongTextField('text', Dict::S('UI:DashletPlainText:Prop-Text'), $this->aProperties['text']);
$oField->SetMandatory();
$oForm->AddField($oField);
}
static public function GetInfo()
{
return array(
'label' => 'Rich text',
'label' => Dict::S('UI:DashletPlainText:Label'),
'icon' => 'images/dashlet-text.png',
'description' => 'Text formatted with HTML tags',
'description' => Dict::S('UI:DashletPlainText:Description'),
);
}
}
@@ -322,8 +331,8 @@ class DashletObjectList extends Dashlet
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['title'] = 'Hardcoded list of "my requests"';
$this->aProperties['query'] = 'SELECT UserRequest AS i WHERE i.caller_id = :current_contact_id AND status NOT IN ("closed", "resolved")';
$this->aProperties['title'] = '';
$this->aProperties['query'] = 'SELECT Contact';
$this->aProperties['menu'] = false;
}
@@ -352,22 +361,23 @@ class DashletObjectList extends Dashlet
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('title', 'Title', $this->aProperties['title']);
$oField = new DesignerTextField('title', Dict::S('UI:DashletObjectList:Prop-Title'), $this->aProperties['title']);
$oForm->AddField($oField);
$oField = new DesignerLongTextField('query', 'Query', $this->aProperties['query']);
$oField = new DesignerLongTextField('query', Dict::S('UI:DashletObjectList:Prop-Query'), $this->aProperties['query']);
$oField->SetMandatory();
$oForm->AddField($oField);
$oField = new DesignerBooleanField('menu', 'Menu', $this->aProperties['menu']);
$oField = new DesignerBooleanField('menu', Dict::S('UI:DashletObjectList:Prop-Menu'), $this->aProperties['menu']);
$oForm->AddField($oField);
}
static public function GetInfo()
{
return array(
'label' => 'Object list',
'label' => Dict::S('UI:DashletObjectList:Label'),
'icon' => 'images/dashlet-list.png',
'description' => 'Object list dashlet',
'description' => Dict::S('UI:DashletObjectList:Description'),
);
}
@@ -376,15 +386,16 @@ class DashletObjectList extends Dashlet
return true;
}
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL)
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL = null)
{
$oField = new DesignerTextField('title', 'Title', '');
$oField = new DesignerTextField('title', Dict::S('UI:DashletObjectList:Prop-Title'), '');
$oForm->AddField($oField);
$oField = new DesignerHiddenField('query', 'Query', $sOQL);
$oField = new DesignerHiddenField('query', Dict::S('UI:DashletObjectList:Prop-Query'), $sOQL);
$oField->SetMandatory();
$oForm->AddField($oField);
$oField = new DesignerBooleanField('menu', 'Menu', $this->aProperties['menu']);
$oField = new DesignerBooleanField('menu', Dict::S('UI:DashletObjectList:Prop-Menu'), $this->aProperties['menu']);
$oForm->AddField($oField);
}
}
@@ -394,9 +405,9 @@ abstract class DashletGroupBy extends Dashlet
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['title'] = 'Contacts grouped by location';
$this->aProperties['title'] = '';
$this->aProperties['query'] = 'SELECT Contact';
$this->aProperties['group_by'] = 'location_name';
$this->aProperties['group_by'] = 'status';
$this->aProperties['style'] = 'table';
}
@@ -407,43 +418,52 @@ abstract class DashletGroupBy extends Dashlet
$sGroupBy = $this->aProperties['group_by'];
$sStyle = $this->aProperties['style'];
if ($sQuery == '')
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
$oFilter = DBObjectSearch::FromOQL($sQuery);
$sClass = $oFilter->GetClass();
$sClassAlias = $oFilter->GetClassAlias();
// Check groupby... it can be wrong at this stage
if (preg_match('/^(.*):(.*)$/', $sGroupBy, $aMatches))
{
$oPage->add('<p>Please enter a valid OQL query</p>');
}
elseif ($sGroupBy == '')
{
$oPage->add('<p>Please select the field on which the objects will be grouped together</p>');
$sAttCode = $aMatches[1];
$sFunction = $aMatches[2];
}
else
{
$oFilter = DBObjectSearch::FromOQL($sQuery);
$sClassAlias = $oFilter->GetClassAlias();
if (preg_match('/^(.*):(.*)$/', $sGroupBy, $aMatches))
$sAttCode = $sGroupBy;
$sFunction = null;
}
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
$oPage->add('<p>'.Dict::S('UI:DashletGroupBy:MissingGroupBy').'</p>');
}
else
{
$sAttLabel = MetaModel::GetLabel($sClass, $sAttCode);
if (!is_null($sFunction))
{
$sAttCode = $aMatches[1];
$sFunction = $aMatches[2];
switch($sFunction)
{
case 'hour':
$sGroupByLabel = 'Hour of '.$sAttCode. ' (0-23)';
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%H')"; // 0 -> 31
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Hour', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%H')"; // 0 -> 23
break;
case 'month':
$sGroupByLabel = 'Month of '.$sAttCode. ' (1 - 12)';
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Month', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%m')"; // 0 -> 31
break;
case 'day_of_week':
$sGroupByLabel = 'Day of week for '.$sAttCode. ' (sunday to saturday)';
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:DayOfWeek', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%w')";
break;
case 'day_of_month':
$sGroupByLabel = 'Day of month for'.$sAttCode;
$sGroupByLabel = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:DayOfMonth', $sAttLabel);
$sGroupByExpr = "DATE_FORMAT($sClassAlias.$sAttCode, '%e')"; // 0 -> 31
break;
@@ -454,10 +474,8 @@ abstract class DashletGroupBy extends Dashlet
}
else
{
$sAttCode = $sGroupBy;
$sGroupByExpr = $sClassAlias.'.'.$sAttCode;
$sGroupByLabel = MetaModel::GetLabel($oFilter->GetClass(), $sAttCode);
$sGroupByLabel = $sAttLabel;
}
switch($sStyle)
@@ -507,57 +525,65 @@ abstract class DashletGroupBy extends Dashlet
}
}
protected function GetGroupByOptions($sOql)
{
$oSearch = DBObjectSearch::FromOQL($sOql);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
if ($oAttDef instanceof AttributeFriendlyName) continue;
if ($oAttDef instanceof AttributeExternalField) continue;
$sLabel = $oAttDef->GetLabel();
$aGroupBy[$sAttCode] = $sLabel;
if ($oAttDef instanceof AttributeDateTime)
{
$aGroupBy[$sAttCode.':hour'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Hour', $sLabel);
$aGroupBy[$sAttCode.':month'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Month', $sLabel);
$aGroupBy[$sAttCode.':day_of_week'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-DayOfWeek', $sLabel);
$aGroupBy[$sAttCode.':day_of_month'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-DayOfMonth', $sLabel);
}
}
asort($aGroupBy);
return $aGroupBy;
}
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('title', 'Title', $this->aProperties['title']);
$oField = new DesignerTextField('title', Dict::S('UI:DashletGroupBy:Prop-Title'), $this->aProperties['title']);
$oForm->AddField($oField);
$oField = new DesignerLongTextField('query', 'Query', $this->aProperties['query']);
$oField = new DesignerLongTextField('query', Dict::S('UI:DashletGroupBy:Prop-Query'), $this->aProperties['query']);
$oField->SetMandatory();
$oForm->AddField($oField);
try
{
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
$aGroupBy = $this->GetGroupByOptions($this->aProperties['query']);
$sLabel = $oAttDef->GetLabel();
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
{
$sLabel = $oAttDef->GetLabel().' (strict)';
}
$aGroupBy[$sAttCode] = $sLabel;
if ($oAttDef instanceof AttributeDateTime)
{
$aGroupBy[$sAttCode.':hour'] = $oAttDef->GetLabel().' (hour)';
$aGroupBy[$sAttCode.':month'] = $oAttDef->GetLabel().' (month)';
$aGroupBy[$sAttCode.':day_of_week'] = $oAttDef->GetLabel().' (day of week)';
$aGroupBy[$sAttCode.':day_of_month'] = $oAttDef->GetLabel().' (day of month)';
}
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField = new DesignerComboField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetMandatory();
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
$oField = new DesignerTextField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetReadOnly();
}
$oForm->AddField($oField);
$aStyles = array(
'pie' => 'Pie chart',
'bars' => 'Bar chart',
'table' => 'Table',
'pie' => Dict::S('UI:DashletGroupByPie:Label'),
'bars' => Dict::S('UI:DashletGroupByBars:Label'),
'table' => Dict::S('UI:DashletGroupByTable:Label'),
);
$oField = new DesignerComboField('style', 'Style', $this->aProperties['style']);
$oField = new DesignerComboField('style', Dict::S('UI:DashletGroupBy:Prop-Style'), $this->aProperties['style']);
$oField->SetMandatory();
$oField->SetAllowedValues($aStyles);
$oForm->AddField($oField);
}
@@ -616,10 +642,11 @@ abstract class DashletGroupBy extends Dashlet
static public function GetInfo()
{
// Note: no need to translate, should never be visible to the end-user!
return array(
'label' => 'Objects grouped by...',
'icon' => 'images/dashlet-object-grouped.png',
'description' => 'Grouped objects dashlet',
'description' => 'Grouped objects dashlet (abstract)',
);
}
@@ -628,44 +655,32 @@ abstract class DashletGroupBy extends Dashlet
return true;
}
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL)
public function GetPropertiesFieldsFromOQL(DesignerForm $oForm, $sOQL = null)
{
$oField = new DesignerTextField('title', 'Title', '');
$oField = new DesignerTextField('title', Dict::S('UI:DashletGroupBy:Prop-Title'), '');
$oForm->AddField($oField);
$oField = new DesignerHiddenField('query', 'Query', $sOQL);
$oField = new DesignerHiddenField('query', Dict::S('UI:DashletGroupBy:Prop-Query'), $sOQL);
$oField->SetMandatory();
$oForm->AddField($oField);
try
if (!is_null($sOQL))
{
// Group by field: build the list of possible values (attribute codes + ...)
$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
$sClass = $oSearch->GetClass();
$aGroupBy = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
{
if (!$oAttDef->IsScalar()) continue; // skip link sets
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue; // skip external keys
$aGroupBy[$sAttCode] = $oAttDef->GetLabel();
if ($oAttDef instanceof AttributeDateTime)
{
//date_format(start_date, '%d')
$aGroupBy['date_of_'.$sAttCode] = 'Day of '.$oAttDef->GetLabel();
}
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField = new DesignerComboField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), null);
$aGroupBy = $this->GetGroupByOptions($sOQL);
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
else
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
// Creating a form for reading parameters!
$oField = new DesignerTextField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), null);
}
$oField->SetMandatory();
$oForm->AddField($oField);
$oField = new DesignerHiddenField('style', '', $this->aProperties['style']);
$oField->SetMandatory();
$oForm->AddField($oField);
}
}
@@ -681,69 +696,9 @@ class DashletGroupByPie extends DashletGroupBy
static public function GetInfo()
{
return array(
'label' => 'Pie Chart',
'label' => Dict::S('UI:DashletGroupByPie:Label'),
'icon' => 'images/dashlet-pie-chart.png',
'description' => 'Pie Chart',
);
}
}
class DashletGroupByPie2 extends DashletGroupByPie
{
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$sTitle = addslashes($this->aProperties['title']);
$sQuery = $this->aProperties['query'];
$sGroupBy = $this->aProperties['group_by'];
$oSearch = DBObjectSearch::FromOQL($sQuery);
$sClassAlias = $oSearch->GetClassAlias();
$aQueryParams = array();
$aGroupBy = array();
$oGroupByExp = Expression::FromOQL($sClassAlias.'.'.$sGroupBy);
$aGroupBy['grouped_by_1'] = $oGroupByExp;
$sSql = MetaModel::MakeGroupByQuery($oSearch, $aQueryParams, $aGroupBy);
$aRes = CMDBSource::QueryToArray($sSql);
$aGroupBy = array();
$aLabels = array();
$iTotalCount = 0;
foreach ($aRes as $aRow)
{
$sValue = $aRow['grouped_by_1'];
$aLabels[] = ($sValue == '') ? 'Empty (%%.%%)' : $sValue.' (%%.%%)'; //TODO: localize
$aGroupBy[] = (int) $aRow['_itop_count_'];
$iTotalCount += $aRow['_itop_count_'];
}
$aURLs = array();
$sContext = ''; //TODO get the context ??
foreach($aGroupBy as $sValue => $iValue)
{
// Build the search for this subset
$oSubsetSearch = clone $oSearch;
$oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($sValue));
$oSubsetSearch->AddConditionExpression($oCondition);
// Todo - à finir
$aURLs[] = 'http://www.combodo.com/itop'; //utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&format=html{$sContext}&filter=".urlencode($oSubsetSearch->serialize());
}
$sJSValues = json_encode($aGroupBy);
$sJSHrefs = json_encode($aURLs);
$sJSLabels = json_encode($aLabels);
$sId = 'chart_'.($bEditMode? 'edit_' : '').$this->sId;
$oPage->add('<div id="chart_'.$sId.'" class="dashlet-content"></div>');
$oPage->add_ready_script("$('#chart_{$sId}').pie_chart({chart_label: '$sTitle', values: $sJSValues, labels: $sJSLabels, hrefs: $sJSHrefs });");
}
static public function GetInfo()
{
return array(
'label' => 'Pie (Raphael)',
'icon' => 'images/dashlet-pie-chart.png',
'description' => 'Pure JS Pie Chart',
'description' => Dict::S('UI:DashletGroupByPie:Description'),
);
}
}
@@ -760,9 +715,9 @@ class DashletGroupByBars extends DashletGroupBy
static public function GetInfo()
{
return array(
'label' => 'Bar Chart',
'label' => Dict::S('UI:DashletGroupByBars:Label'),
'icon' => 'images/dashlet-bar-chart.png',
'description' => 'Bar Chart',
'description' => Dict::S('UI:DashletGroupByBars:Description'),
);
}
}
@@ -778,9 +733,9 @@ class DashletGroupByTable extends DashletGroupBy
static public function GetInfo()
{
return array(
'label' => 'Group By (table)',
'label' => Dict::S('UI:DashletGroupByTable:Label'),
'description' => Dict::S('UI:DashletGroupByTable:Description'),
'icon' => 'images/dashlet-groupby-table.png',
'description' => 'List (Grouped by a field)',
);
}
}
@@ -791,8 +746,10 @@ class DashletHeaderStatic extends Dashlet
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['title'] = 'Contacts';
$this->aProperties['icon'] = 'itop-config-mgmt-1.0.0/images/contact.png';
$this->aProperties['title'] = Dict::S('UI:DashletHeaderStatic:Prop-Title:Default');
$sIcon = MetaModel::GetClassIcon('Contact', false);
$sIcon = str_replace(utils::GetAbsoluteUrlModulesRoot(), '', $sIcon);
$this->aProperties['icon'] = $sIcon;
}
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
@@ -814,10 +771,10 @@ class DashletHeaderStatic extends Dashlet
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('title', 'Title', $this->aProperties['title']);
$oField = new DesignerTextField('title', Dict::S('UI:DashletHeaderStatic:Prop-Title'), $this->aProperties['title']);
$oForm->AddField($oField);
$oField = new DesignerIconSelectionField('icon', 'Icon', $this->aProperties['icon']);
$oField = new DesignerIconSelectionField('icon', Dict::S('UI:DashletHeaderStatic:Prop-Icon'), $this->aProperties['icon']);
$aAllIcons = self::FindIcons(APPROOT.'env-'.utils::GetCurrentEnvironment());
ksort($aAllIcons);
$aValues = array();
@@ -832,9 +789,9 @@ class DashletHeaderStatic extends Dashlet
static public function GetInfo()
{
return array(
'label' => 'Header',
'label' => Dict::S('UI:DashletHeaderStatic:Label'),
'icon' => 'images/dashlet-header.png',
'description' => 'Header with stats (grouped by...)',
'description' => Dict::S('UI:DashletHeaderStatic:Description'),
);
}
@@ -869,9 +826,11 @@ class DashletHeaderDynamic extends Dashlet
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['title'] = 'Contacts';
$this->aProperties['icon'] = 'itop-config-mgmt-1.0.0/images/contact.png';
$this->aProperties['subtitle'] = 'Contacts';
$this->aProperties['title'] = Dict::S('UI:DashletHeaderDynamic:Prop-Title:Default');
$sIcon = MetaModel::GetClassIcon('Contact', false);
$sIcon = str_replace(utils::GetAbsoluteUrlModulesRoot(), '', $sIcon);
$this->aProperties['icon'] = $sIcon;
$this->aProperties['subtitle'] = Dict::S('UI:DashletHeaderDynamic:Prop-Subtitle:Default');
$this->aProperties['query'] = 'SELECT Contact';
$this->aProperties['group_by'] = 'status';
$this->aProperties['values'] = array('active', 'inactive');
@@ -939,10 +898,10 @@ class DashletHeaderDynamic extends Dashlet
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('title', 'Title', $this->aProperties['title']);
$oField = new DesignerTextField('title', Dict::S('UI:DashletHeaderDynamic:Prop-Title'), $this->aProperties['title']);
$oForm->AddField($oField);
$oField = new DesignerIconSelectionField('icon', 'Icon', $this->aProperties['icon']);
$oField = new DesignerIconSelectionField('icon', Dict::S('UI:DashletHeaderDynamic:Prop-Icon'), $this->aProperties['icon']);
$aAllIcons = DashletHeaderStatic::FindIcons(APPROOT.'env-'.utils::GetCurrentEnvironment());
ksort($aAllIcons);
$aValues = array();
@@ -953,10 +912,11 @@ class DashletHeaderDynamic extends Dashlet
$oField->SetAllowedValues($aValues);
$oForm->AddField($oField);
$oField = new DesignerTextField('subtitle', 'Subtitle', $this->aProperties['subtitle']);
$oField = new DesignerTextField('subtitle', Dict::S('UI:DashletHeaderDynamic:Prop-Subtitle'), $this->aProperties['subtitle']);
$oForm->AddField($oField);
$oField = new DesignerTextField('query', 'Query', $this->aProperties['query']);
$oField = new DesignerTextField('query', Dict::S('UI:DashletHeaderDynamic:Prop-Query'), $this->aProperties['query']);
$oField->SetMandatory();
$oForm->AddField($oField);
try
@@ -971,16 +931,18 @@ class DashletHeaderDynamic extends Dashlet
$sLabel = $oAttDef->GetLabel();
$aGroupBy[$sAttCode] = $sLabel;
}
$oField = new DesignerComboField('group_by', 'Group by', $this->aProperties['group_by']);
$oField = new DesignerComboField('group_by', Dict::S('UI:DashletHeaderDynamic:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetMandatory();
$oField->SetAllowedValues($aGroupBy);
}
catch(Exception $e)
{
$oField = new DesignerTextField('group_by', 'Group by', $this->aProperties['group_by']);
$oField = new DesignerTextField('group_by', Dict::S('UI:DashletHeaderDynamic:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetMandatory();
}
$oForm->AddField($oField);
$oField = new DesignerComboField('values', 'Values (CSV list)', $this->aProperties['values']);
$oField = new DesignerComboField('values', Dict::S('UI:DashletHeaderDynamic:Prop-Values'), $this->aProperties['values']);
$oField->MultipleSelection(true);
if (MetaModel::IsValidAttCode($sClass, $this->aProperties['group_by']))
{
@@ -1032,9 +994,9 @@ class DashletHeaderDynamic extends Dashlet
static public function GetInfo()
{
return array(
'label' => 'Header with statistics',
'label' => Dict::S('UI:DashletHeaderDynamic:Label'),
'icon' => 'images/dashlet-header-stats.png',
'description' => 'Header with stats (grouped by...)',
'description' => Dict::S('UI:DashletHeaderDynamic:Description'),
);
}
}
@@ -1092,7 +1054,7 @@ class DashletBadge extends Dashlet
}
$oField = new DesignerIconSelectionField('class', 'Class', $this->aProperties['class']);
$oField = new DesignerIconSelectionField('class', Dict::S('UI:DashletBadge:Prop-Class'), $this->aProperties['class']);
ksort($aClasses);
$aValues = array();
foreach($aClasses as $sClass => $sClass)
@@ -1106,7 +1068,7 @@ class DashletBadge extends Dashlet
// The icon does not exist, leet's use a transparent one of the same size.
$sIconUrl = utils::GetAbsoluteUrlAppRoot().'images/transparent_32_32.png';
}
$aValues[] = array('value' => $sClass, 'label' => $sClass, 'icon' => $sIconUrl);
$aValues[] = array('value' => $sClass, 'label' => MetaModel::GetName($sClass), 'icon' => $sIconUrl);
}
}
$oField->SetAllowedValues($aValues);
@@ -1117,292 +1079,10 @@ class DashletBadge extends Dashlet
static public function GetInfo()
{
return array(
'label' => 'Badge',
'label' => Dict::S('UI:DashletBadge:Label'),
'icon' => 'images/dashlet-badge.png',
'description' => 'Object Icon with new/search',
);
}
}
class DashletProto extends Dashlet
{
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['class'] = 'Foo';
}
protected $aValues1;
protected $aValues2;
protected $aStats;
protected $sGroupByLabel1;
protected $sGroupByLabel2;
protected $iTotalCount;
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$this->Compute();
//$sHtmlTitle = $this->aProperties['title'];
$sHtmlTitle = "Group by made on two dimensions";
// Build the output
$oPage->add('<div style="text-align:center" class="dashlet-content">');
$oPage->add('<h1>'.$sHtmlTitle.'</h1>');
$oPage->p(Dict::Format('UI:Pagination:HeaderNoSelection', $this->iTotalCount));
$oPage->add('<table>');
// Header
$oPage->add('<tr>');
$oPage->add('<td></td>');
foreach ($this->aValues2 as $sValue2 => $sDisplayValue2)
{
$oPage->add('<td><b>'.$sDisplayValue2.'</b></td>');
}
$oPage->add('</tr>');
// Contents
foreach ($this->aValues1 as $sValue1 => $sDisplayValue1)
{
$oPage->add('<tr>');
$oPage->add('<td><b>'.$sDisplayValue1.'</b></td>');
foreach ($this->aValues2 as $sValue2 => $sDisplayValue2)
{
@$aResData = $this->aStats[$sValue1][$sValue2];
if (is_array($aResData))
{
$sRes = '<a href="'.$aResData['href'].'">'.$aResData['count'].'</a>';
}
else
{
// Missing result => 0
$sRes = '-';
}
$oPage->add('<td>'.$sRes.'</td>');
}
$oPage->add('</tr>');
}
$oPage->add('</table>');
$oPage->add('</div>');
$sId = 'chart_'.($bEditMode? 'edit_' : '').$this->sId;
$oPage->add('<div id="chart_'.$sId.'" class="dashlet-content"></div>');
$aAxisX = $this->aValues1;
$aAxisY = $this->aValues2;
$aData = array();
$aHref = array();
foreach ($this->aValues1 as $sValue1 => $sDisplayValue1)
{
foreach ($this->aValues2 as $sValue2 => $sDisplayValue2)
{
@$aResData = $this->aStats[$sValue1][$sValue2];
if (is_array($aResData))
{
$aData[$sValue1][$sValue2] = $aResData['count'];
$aHref[$sValue1][$sValue2] = $aResData['href'];
}
else
{
// Missing result => 0
$aData[$sValue1][$sValue2] = 0;
$aHref[$sValue1][$sValue2] = '';
}
}
}
$sJSAxisX = json_encode($aAxisX);
$sJSAxisY = json_encode($aAxisY);
$sJSData = json_encode($aData);
$sJSHref = json_encode($aHref);
$sTitle = addslashes($sHtmlTitle);
$oPage->add_ready_script("$('#chart_{$sId}').heatmap_chart({chart_label: '$sTitle', values: $sJSData, hrefs: $sJSHref, axis_x: $sJSAxisX, axis_y: $sJSAxisY});");
}
protected function Compute()
{
// Read and interpret parameters
//
//$sFoo = $this->aProperties['foo'];
if (false)
{
$oFilter = DBObjectSearch::FromOQL('SELECT FunctionalCI');
$sGroupBy1 = 'FunctionalCI.status';
$this->sGroupByLabel1 = MetaModel::GetLabel('FunctionalCI', 'status');
$aFill1 = array(
'production',
'implementation',
);
$aFill1 = null;
//$sGroupBy2 = 'org_id_friendlyname';
$sGroupBy2 = 'FunctionalCI.org_id';
$this->sGroupByLabel2 = MetaModel::GetLabel('FunctionalCI', 'org_id');
$aFill2 = array(
'2',
'1',
);
//$aFill2 = null;
}
else
{
$oFilter = DBObjectSearch::FromOQL('SELECT Incident AS i');
$sGroupBy1 = "DATE_FORMAT(i.start_date, '%H')";
$this->sGroupByLabel1 = 'Hour of '.MetaModel::GetLabel('Incident', 'start_date');
$aFill1 = array(9, 10, 11, 12, 13, 14, 15, 16, 17, 18);
//$aFill1 = null;
$sGroupBy2 = "DATE_FORMAT(i.start_date, '%w')";
$this->sGroupByLabel2 = 'Week day of '.MetaModel::GetLabel('Incident', 'start_date');
$aFill2 = array(1, 2, 3, 4, 5);
//$aFill2 = null;
}
// Do compute the statistics
//
$this->aValues1 = array();
$this->aValues2 = array();
$this->aStats = array();
$this->iTotalCount = 0;
$sAlias = $oFilter->GetClassAlias();
//$oGroupByExp1 = new FieldExpression($sGroupBy1, $sAlias);
$oGroupByExp1 = Expression::FromOQL($sGroupBy1);
//$oGroupByExp2 = new FieldExpression($sGroupBy2, $sAlias);
$oGroupByExp2 = Expression::FromOQL($sGroupBy2);
$aGroupBy = array();
$aGroupBy['grouped_by_1'] = $oGroupByExp1;
$aGroupBy['grouped_by_2'] = $oGroupByExp2;
$sSql = MetaModel::MakeGroupByQuery($oFilter, array(), $aGroupBy);
$aRes = CMDBSource::QueryToArray($sSql);
// Prepare a blank and ordered grid
if (is_array($aFill1))
{
foreach ($aFill1 as $sValue1)
{
$sDisplayValue1 = $aGroupBy['grouped_by_1']->MakeValueLabel($oFilter, $sValue1, $sValue1); // default to the raw value
$this->aValues1[$sValue1] = $sDisplayValue1;
}
}
if (is_array($aFill2))
{
foreach ($aFill2 as $sValue2)
{
$sDisplayValue2 = $aGroupBy['grouped_by_2']->MakeValueLabel($oFilter, $sValue2, $sValue2); // default to the raw value
$this->aValues2[$sValue2] = $sDisplayValue2;
}
}
$oAppContext = new ApplicationContext();
$sParams = $oAppContext->GetForLink();
foreach ($aRes as $aRow)
{
$iCount = $aRow['_itop_count_'];
$this->iTotalCount += $iCount;
$sValue1 = $aRow['grouped_by_1'];
$sValue2 = $aRow['grouped_by_2'];
$bValidResult = true;
if (is_array($aFill1) && !in_array($sValue1, $aFill1))
{
$bValidResult = false;
}
if (is_array($aFill2) && !in_array($sValue2, $aFill2))
{
$bValidResult = false;
}
if ($bValidResult)
{
// Build the search for this subset
$oSubsetSearch = clone $oFilter;
$oCondition = new BinaryExpression($oGroupByExp1, '=', new ScalarExpression($sValue1));
$oSubsetSearch->AddConditionExpression($oCondition);
$oCondition = new BinaryExpression($oGroupByExp2, '=', new ScalarExpression($sValue2));
$oSubsetSearch->AddConditionExpression($oCondition);
$sFilter = urlencode($oSubsetSearch->serialize());
$this->aStats[$sValue1][$sValue2] = array (
'href' => utils::GetAbsoluteUrlAppRoot()."pages/UI.php?operation=search&dosearch=1&$sParams&filter=".urlencode($sFilter),
'count' => $iCount,
);
if (!array_key_exists($sValue1, $this->aValues1))
{
$sDisplayValue1 = $aGroupBy['grouped_by_1']->MakeValueLabel($oFilter, $sValue1, $sValue1); // default to the raw value
$this->aValues1[$sValue1] = $sDisplayValue1;
}
if (!array_key_exists($sValue2, $this->aValues2))
{
$sDisplayValue2 = $aGroupBy['grouped_by_2']->MakeValueLabel($oFilter, $sValue2, $sValue2); // default to the raw value
$this->aValues2[$sValue2] = $sDisplayValue2;
}
}
}
}
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('class', 'Class', $this->aProperties['class']);
$oForm->AddField($oField);
}
static public function GetInfo()
{
return array(
'label' => 'Test3D',
'icon' => 'images/dashlet-groupby2-table.png',
'description' => 'Group by on two dimensions',
);
}
}
class DashletHeatMap extends Dashlet
{
public function __construct($sId)
{
parent::__construct($sId);
$this->aProperties['class'] = 'Contact';
$this->aProperties['title'] = 'Test';
}
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
{
$sTitle = addslashes($this->aProperties['title']);
$sId = 'chart_'.($bEditMode? 'edit_' : '').$this->sId;
$oPage->add('<div id="chart_'.$sId.'" class="dashlet-content"></div>');
$aAxisX = array(0 => 'Lun', 1 => 'Ma');
$aAxisY = array(0 => '12h', 1 => '13h');
$aData = array(
0 => array(1, 2),
1 => array(3, 4),
);
$sJSAxisX = json_encode($aAxisX);
$sJSAxisY = json_encode($aAxisY);
$sJSData = json_encode($aData);
$oPage->add_ready_script("$('#chart_{$sId}').heatmap_chart({chart_label: '$sTitle', values: $sJSData, axis_x: $sJSAxisX, axis_y: $sJSAxisY});");
}
public function GetPropertiesFields(DesignerForm $oForm)
{
$oField = new DesignerTextField('title', 'Title', $this->aProperties['title']);
$oForm->AddField($oField);
$oField = new DesignerTextField('class', 'Class', $this->aProperties['class']);
$oForm->AddField($oField);
}
static public function GetInfo()
{
return array(
'label' => 'Heatmap (Raphael)',
'icon' => 'images/dashlet-heatmap.png',
'description' => 'Pure JS Heat Map Chart',
'description' => Dict::S('UI:DashletBadge:Description'),
);
}
}
?>

View File

@@ -656,7 +656,8 @@ class DisplayBlock
$iCount = $this->m_oSet->Count();
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.urlencode($this->m_oFilter->serialize());
$sHtml .= '<p><a class="actions" href="'.$sHyperlink.'">';
$sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;');
// Note: border set to 0 due to various browser interpretations (IE9 adding a 2px border)
$sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;border:0;');
$sHtml .= MetaModel::GetName($sClass).': '.$iCount.'</a></p>';
$sParams = $oAppContext->GetForLink();
$sHtml .= '<p>';

View File

@@ -92,7 +92,9 @@ class DesignerForm
$aRow = $oField->Render($oP, $sFormId);
if ($oField->IsVisible())
{
$aDetails[] = array('label' => $aRow['label'], 'value' => $aRow['value']);
$sValidation = '&nbsp;<span class="prop_apply">'.$this->GetValidationArea($oField->GetCode()).'</span>';
$sField = $aRow['value'].$sValidation;
$aDetails[] = array('label' => $aRow['label'], 'value' => $sField);
}
else
{
@@ -152,7 +154,7 @@ class DesignerForm
$sFormId = $this->sFormId;
$sReturn = '<form id="'.$sFormId.'" onsubmit="return false;">';
$sReturn .= '<table class="prop_table">';
$sReturn .= '<thead><tr><th class="prop_header">Property</th><th class="prop_header">Value</th><th colspan="2" class="prop_header">&nbsp;</th></tr></thead><tbody>';
$sReturn .= '<thead><tr><th class="prop_header">'.Dict::S('UI:Form:Property').'</th><th class="prop_header">'.Dict::S('UI:Form:Value').'</th><th colspan="2" class="prop_header">&nbsp;</th></tr></thead><tbody>';
}
else
{
@@ -168,13 +170,14 @@ class DesignerForm
}
$sValidationFields = '</td><td class="prop_icon prop_apply"><span title="Apply" class="ui-icon ui-icon-circle-check"/></td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td></tr>';
foreach($aFields as $oField)
{
$aRow = $oField->Render($oP, $sFormId, 'property');
if ($oField->IsVisible())
{
$sFieldId = $this->GetFieldId($oField->GetCode());
$sValidation = $this->GetValidationArea($oField->GetCode(), '<span title="Apply" class="ui-icon ui-icon-circle-check"/>');
$sValidationFields = '</td><td class="prop_icon prop_apply">'.$sValidation.'</td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td></tr>';
$sReturn .= '<tr id="row_'.$sFieldId.'"><td class="prop_label">'.$aRow['label'].'</td><td class="prop_value">'.$aRow['value'];
if (!($oField instanceof DesignerFormSelectorField))
{
@@ -359,9 +362,9 @@ EOF
return 'attr_'.$sCode;
}
public function GetValidationArea($sCode)
public function GetValidationArea($sCode, $sContent = '')
{
return "<span style=\"display:inline-block;width:20px;\" id=\"v_{$this->sFormPrefix}attr_$sCode\"></span>";
return "<span style=\"display:inline-block;width:20px;\" id=\"v_{$this->sFormPrefix}attr_$sCode\"><span class=\"ui-icon ui-icon-alert\"></span>$sContent</span>";
}
public function GetAsyncActionClass()
{
@@ -600,7 +603,6 @@ class DesignerTextField extends DesignerFormField
{
$sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode);
$sValidation = $this->oForm->GetValidationArea($this->sCode);
$sPattern = addslashes($this->sValidationPattern);
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'readonly' : '';
@@ -613,7 +615,7 @@ $('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId'
}
EOF
);
return array('label' => $this->sLabel, 'value' => "<input type=\"text\" id=\"$sId\" $sReadOnly name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">".$sValidation);
return array('label' => $this->sLabel, 'value' => "<input type=\"text\" id=\"$sId\" $sReadOnly name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">");
}
public function ReadParam(&$aValues)
@@ -633,7 +635,6 @@ class DesignerLongTextField extends DesignerTextField
{
$sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode);
$sValidation = $this->oForm->GetValidationArea($this->sCode);
$sPattern = addslashes($this->sValidationPattern);
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'readonly' : '';
@@ -646,7 +647,7 @@ $('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId'
}
EOF
);
return array('label' => $this->sLabel, 'value' => "<textarea id=\"$sId\" $sReadOnly name=\"$sName\">".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."</textarea>".$sValidation);
return array('label' => $this->sLabel, 'value' => "<textarea id=\"$sId\" $sReadOnly name=\"$sName\">".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."</textarea>");
}
}
@@ -688,7 +689,6 @@ class DesignerComboField extends DesignerFormField
$sChecked = $this->defaultValue ? 'checked' : '';
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
$sValidation = $this->oForm->GetValidationArea($this->sCode);
if ($this->bMultipleSelection)
{
$sHtml = "<select multiple size=\"8\"id=\"$sId\" name=\"$sName\" $sReadOnly>";
@@ -722,7 +722,7 @@ class DesignerComboField extends DesignerFormField
$('#$sId').bind('change validate', function() { ValidateWithPattern('$sId', $sMandatory, '', '$sFormId'); } );
EOF
);
return array('label' => $this->sLabel, 'value' => $sHtml.$sValidation);
return array('label' => $this->sLabel, 'value' => $sHtml);
}
public function ReadParam(&$aValues)
@@ -746,11 +746,10 @@ class DesignerBooleanField extends DesignerFormField
{
$sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode);
$sValidation = $this->oForm->GetValidationArea($this->sCode);
$sChecked = $this->defaultValue ? 'checked' : '';
$sReadOnly = $this->IsReadOnly() ? 'disabled' : ''; // readonly does not work as expected on checkboxes:
// readonly prevents the user from changing the input's value not its state (checked/unchecked)
return array('label' => $this->sLabel, 'value' => "<input type=\"checkbox\" $sChecked $sReadOnly id=\"$sId\" name=\"$sName\" value=\"true\">".$sValidation);
return array('label' => $this->sLabel, 'value' => "<input type=\"checkbox\" $sChecked $sReadOnly id=\"$sId\" name=\"$sName\" value=\"true\">");
}
public function ReadParam(&$aValues)
@@ -800,7 +799,6 @@ class DesignerHiddenField extends DesignerFormField
{
$sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode);
$sValidation = $this->oForm->GetValidationArea($this->sCode);
$sChecked = $this->defaultValue ? 'checked' : '';
return array('label' =>'', 'value' => "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\">");
}
@@ -868,7 +866,6 @@ class DesignerSortableField extends DesignerFormField
$bOpen = false;
$sId = $this->oForm->GetFieldId($this->sCode);
$sName = $this->oForm->GetFieldName($this->sCode);
$sValidation = $this->oForm->GetValidationArea($this->sCode);
$sHtml = "<span class=\"sort_$sId fieldslist\" id=\"sortable_$sId\">";
foreach($this->defaultValue as $sValue)
{
@@ -893,7 +890,7 @@ class DesignerSortableField extends DesignerFormField
$('#sortable_$sId').disableSelection();
EOF
);
return array('label' => $this->sLabel, 'value' => $sHtml.$sValidation);
return array('label' => $this->sLabel, 'value' => $sHtml);
}
}

View File

@@ -397,17 +397,6 @@ EOF
EOF
);
// Build menus from module handlers
//
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMenuCreation');
call_user_func($aCallSpec);
}
}
}
public function AddToMenu($sHtml)

View File

@@ -60,10 +60,29 @@ require_once(APPROOT."/application/user.dashboard.class.inc.php");
class ApplicationMenu
{
static $bAdditionalMenusLoaded = false;
static $aRootMenus = array();
static $aMenusIndex = array();
static $sFavoriteSiloQuery = 'SELECT Organization';
static public function LoadAdditionalMenus()
{
if (!self::$bAdditionalMenusLoaded)
{
// Build menus from module handlers
//
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMenuCreation');
call_user_func($aCallSpec);
}
}
self::$bAdditionalMenusLoaded = true;
}
}
/**
* Set the query used to limit the list of displayed organizations in the drop-down menu
* @param $sOQL string The OQL query returning a list of Organization objects
@@ -127,6 +146,7 @@ class ApplicationMenu
*/
static public function ReflectionMenuNodes()
{
self::LoadAdditionalMenus();
return self::$aMenusIndex;
}
@@ -135,6 +155,7 @@ class ApplicationMenu
*/
static public function DisplayMenu(iTopWebPage $oPage, $aExtraParams)
{
self::LoadAdditionalMenus();
// Sort the root menu based on the rank
usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
$iAccordion = 0;

View File

@@ -847,15 +847,20 @@ class FunctionExpression extends Expression
$oFormatExpr = $this->m_aArgs[1];
if ($oFormatExpr->Render() == "'%w'")
{
static $aWeekDayToString = array(
0 => 'Sunday',
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
);
static $aWeekDayToString = null;
if (is_null($aWeekDayToString))
{
// Init the correspondance table
$aWeekDayToString = array(
0 => Dict::S('DayOfWeek-Sunday'),
1 => Dict::S('DayOfWeek-Monday'),
2 => Dict::S('DayOfWeek-Tuesday'),
3 => Dict::S('DayOfWeek-Wednesday'),
4 => Dict::S('DayOfWeek-Thursday'),
5 => Dict::S('DayOfWeek-Friday'),
6 => Dict::S('DayOfWeek-Saturday')
);
}
if (isset($aWeekDayToString[(int)$sValue]))
{
$sRes = $aWeekDayToString[(int)$sValue];

View File

@@ -50,6 +50,12 @@ class OQLException extends CoreException
parent::__construct($sMessage, 0);
}
public function GetUserFriendlyDescription()
{
// Todo - translate all errors!
return $this->getMessage();
}
public function getHtmlDesc($sHighlightHtmlBegin = '<span style="font-weight: bolder">', $sHighlightHtmlEnd = '</span>')
{
$sRet = htmlentities($this->m_MyIssue.", found '".$this->m_sUnexpected."' in: ", ENT_QUOTES, 'UTF-8');

View File

@@ -37,6 +37,21 @@ class UnknownClassOqlException extends OqlNormalizeException
{
parent::__construct('Unknown class', $sInput, $oName, $aExpecting);
}
public function GetUserFriendlyDescription()
{
$sWrongClass = $this->GetWrongWord();
$sSuggest = self::FindClosestString($sWrongClass, $this->GetSuggestions());
if ($sSuggest != '')
{
return Dict::Format('UI:OQL:UnknownClassAndFix', $sWrongClass, $sSuggest);
}
else
{
return Dict::Format('UI:OQL:UnknownClassNoFix', $sWrongClass);
}
}
}
class OqlInterpreterException extends OQLException

View File

@@ -1178,6 +1178,19 @@ table.prop_table {
td.prop_value {
text-align: left;
}
tr.itop-property-field-modified td {
background: #fbb;
}
tr.itop-property-field-modified td.prop_value.hover {
background: #fbb;
}
td.prop_value textarea, td.prop_value input[type=text]{
width: 98%;
}
td.prop_icon {
width: 20px;
}
.dashlet {
text-align:left;
}
@@ -1193,6 +1206,15 @@ td.prop_value {
.dashlet-content .display_block {
text-align:left;
}
.prop_apply .ui-icon-alert {
display: none;
}
.prop_apply .ui-state-error .ui-icon-alert {
display: block;
}
.ui-state-error .ui-icon-circle-check {
display: none;
}
.summary-details {
float: right;
margin-top: 5px;

View File

@@ -353,6 +353,7 @@ Dict::Add('EN US', 'English', 'English', array(
'UI:Button:Search' => ' Search ',
'UI:Button:Query' => ' Query ',
'UI:Button:Ok' => 'Ok',
'UI:Button:Save' => 'Save',
'UI:Button:Cancel' => 'Cancel',
'UI:Button:Apply' => 'Apply',
'UI:Button:Back' => ' << Back ',
@@ -979,5 +980,87 @@ When associated with a trigger, each action is given an "order" number, specifyi
'UI:Button:MoveUp' => 'Move Up',
'UI:Button:MoveDown' => 'Move Down',
'UI:OQL:UnknownClassAndFix' => 'Unknown class "%1$s". You may try "%2$s" instead.',
'UI:OQL:UnknownClassNoFix' => 'Unknown class "%1$s"',
'UI:Dashboard:Edit' => 'Edit This Page...',
'UI:Dashboard:Revert' => 'Revert To Original Version...',
'UI:Dashboard:RevertConfirm' => 'Every changes made to the original version will be lost. Please confirm that you want to do this.',
'UI:DashletCreation:Title' => 'Create a new Dashlet',
'UI:DashletCreation:Dashboard' => 'Dashboard',
'UI:DashletCreation:DashletType' => 'Dashlet Type',
'UI:DashletCreation:EditNow' => 'Edit the Dashboard',
'UI:DashboardEdit:Title' => 'Dashboard Editor',
'UI:DashboardEdit:DashboardTitle' => 'Title',
'UI:DashboardEdit:Layout' => 'Layout',
'UI:DashboardEdit:Properties' => 'Dashboard Properties',
'UI:DashboardEdit:Dashlets' => 'Available Dashlets',
'UI:DashboardEdit:DashletProperties' => 'Dashlet Properties',
'UI:Form:Property' => 'Property',
'UI:Form:Value' => 'Value',
'UI:DashletPlainText:Label' => 'Text',
'UI:DashletPlainText:Description' => 'Plain text (no formatting)',
'UI:DashletPlainText:Prop-Text' => 'Text',
'UI:DashletPlainText:Prop-Text:Default' => 'Please enter some text here...',
'UI:DashletObjectList:Label' => 'Object list',
'UI:DashletObjectList:Description' => 'Object list dashlet',
'UI:DashletObjectList:Prop-Title' => 'Title',
'UI:DashletObjectList:Prop-Query' => 'Query',
'UI:DashletObjectList:Prop-Menu' => 'Menu',
'UI:DashletGroupBy:Prop-Title' => 'Title',
'UI:DashletGroupBy:Prop-Query' => 'Query',
'UI:DashletGroupBy:Prop-Style' => 'Style',
'UI:DashletGroupBy:Prop-GroupBy' => 'Group by...',
'UI:DashletGroupBy:Prop-GroupBy:Hour' => 'Hour of %1$s (0-23)',
'UI:DashletGroupBy:Prop-GroupBy:Month' => 'Month of %1$s (1 - 12)',
'UI:DashletGroupBy:Prop-GroupBy:DayOfWeek' => 'Day of week for %1$s',
'UI:DashletGroupBy:Prop-GroupBy:DayOfMonth' => 'Day of month for %1$s',
'UI:DashletGroupBy:Prop-GroupBy:Select-Hour' => '%1$s (hour)',
'UI:DashletGroupBy:Prop-GroupBy:Select-Month' => '%1$s (month)',
'UI:DashletGroupBy:Prop-GroupBy:Select-DayOfWeek' => '%1$s (day of week)',
'UI:DashletGroupBy:Prop-GroupBy:Select-DayOfMonth' => '%1$s (day of month)',
'UI:DashletGroupBy:MissingGroupBy' => 'Please select the field on which the objects will be grouped together',
'UI:DashletGroupByPie:Label' => 'Pie Chart',
'UI:DashletGroupByPie:Description' => 'Pie Chart',
'UI:DashletGroupByBars:Label' => 'Bar Chart',
'UI:DashletGroupByBars:Description' => 'Bar Chart',
'UI:DashletGroupByTable:Label' => 'Group By (table)',
'UI:DashletGroupByTable:Description' => 'List (Grouped by a field)',
'UI:DashletHeaderStatic:Label' => 'Header',
'UI:DashletHeaderStatic:Description' => 'Displays an horizontal separator',
'UI:DashletHeaderStatic:Prop-Title' => 'Title',
'UI:DashletHeaderStatic:Prop-Title:Default' => 'Contacts',
'UI:DashletHeaderStatic:Prop-Icon' => 'Icon',
'UI:DashletHeaderDynamic:Label' => 'Header with statistics',
'UI:DashletHeaderDynamic:Description' => 'Header with stats (grouped by...)',
'UI:DashletHeaderDynamic:Prop-Title' => 'Title',
'UI:DashletHeaderDynamic:Prop-Title:Default' => 'Contacts',
'UI:DashletHeaderDynamic:Prop-Icon' => 'Icon',
'UI:DashletHeaderDynamic:Prop-Subtitle' => 'Subtitle',
'UI:DashletHeaderDynamic:Prop-Subtitle:Default' => 'Contacts',
'UI:DashletHeaderDynamic:Prop-Query' => 'Query',
'UI:DashletHeaderDynamic:Prop-GroupBy' => 'Group by',
'UI:DashletHeaderDynamic:Prop-Values' => 'Values',
'UI:DashletBadge:Label' => 'Badge',
'UI:DashletBadge:Description' => 'Object Icon with new/search',
'UI:DashletBadge:Prop-Class' => 'Class',
'DayOfWeek-Sunday' => 'Sunday',
'DayOfWeek-Monday' => 'Monday',
'DayOfWeek-Tuesday' => 'Tuesday',
'DayOfWeek-Wednesday' => 'Wednesday',
'DayOfWeek-Thursday' => 'Thursday',
'DayOfWeek-Friday' => 'Friday',
'DayOfWeek-Saturday' => 'Saturday',
));
?>

View File

@@ -235,6 +235,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'UI:Button:GlobalSearch' => 'Rechercher',
'UI:Button:Search' => 'Rechercher',
'UI:Button:Query' => ' Lancer la requête ',
'UI:Button:Save' => 'Sauver',
'UI:Button:Ok' => 'Ok',
'UI:Button:Cancel' => 'Annuler',
'UI:Button:Apply' => 'Appliquer',
@@ -823,5 +824,87 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
'UI:Button:MoveUp' => 'Monter',
'UI:Button:MoveDown' => 'Descendre',
'UI:OQL:UnknownClassAndFix' => 'La classe "%1$s" est inconnue. Essayez plutôt "%2$s".',
'UI:OQL:UnknownClassNoFix' => 'La classe "%1$s" est inconnue',
'UI:Dashboard:Edit' => 'Editer cette page...',
'UI:Dashboard:Revert' => 'Revenir à la version d\'origine...',
'UI:Dashboard:RevertConfirm' => 'Toutes modifications apportées à la version d\'origine seront perdues. Veuillez confirmer l\'opération.',
'UI:DashletCreation:Title' => 'Créer un Indicateur',
'UI:DashletCreation:Dashboard' => 'Tableau de bord',
'UI:DashletCreation:DashletType' => 'Type d\'Indicateur',
'UI:DashletCreation:EditNow' => 'Modifier le tableau de bord',
'UI:DashboardEdit:Title' => 'Editeur de tableau de bord',
'UI:DashboardEdit:DashboardTitle' => 'Titre',
'UI:DashboardEdit:Layout' => 'Mise en page',
'UI:DashboardEdit:Properties' => 'Propriétés du tableau de bord',
'UI:DashboardEdit:Dashlets' => 'Indicateurs',
'UI:DashboardEdit:DashletProperties' => 'Propriétés de l\'Indicateur',
'UI:Form:Property' => 'Propriété',
'UI:Form:Value' => 'Valeur',
'UI:DashletPlainText:Label' => 'Texte',
'UI:DashletPlainText:Description' => 'Text pur (pas de mise en forme)',
'UI:DashletPlainText:Prop-Text' => 'Texte',
'UI:DashletPlainText:Prop-Text:Default' => 'Veuillez saisir votre texte ici...',
'UI:DashletObjectList:Label' => 'Liste d\'objets',
'UI:DashletObjectList:Description' => 'Liste d\'objets',
'UI:DashletObjectList:Prop-Title' => 'Titre',
'UI:DashletObjectList:Prop-Query' => 'Requête OQL',
'UI:DashletObjectList:Prop-Menu' => 'Menu',
'UI:DashletGroupBy:Prop-Title' => 'Titre',
'UI:DashletGroupBy:Prop-Query' => 'Requête OQL',
'UI:DashletGroupBy:Prop-Style' => 'Style',
'UI:DashletGroupBy:Prop-GroupBy' => 'Grouper par',
'UI:DashletGroupBy:Prop-GroupBy:Hour' => 'Heure de %1$s (0-23)',
'UI:DashletGroupBy:Prop-GroupBy:Month' => 'Mois de %1$s (1 - 12)',
'UI:DashletGroupBy:Prop-GroupBy:DayOfWeek' => 'Jour de la semaine pour %1$s',
'UI:DashletGroupBy:Prop-GroupBy:DayOfMonth' => 'Jour du mois pour %1$s',
'UI:DashletGroupBy:Prop-GroupBy:Select-Hour' => '%1$s (heure)',
'UI:DashletGroupBy:Prop-GroupBy:Select-Month' => '%1$s (mois)',
'UI:DashletGroupBy:Prop-GroupBy:Select-DayOfWeek' => '%1$s (jour de la semaine)',
'UI:DashletGroupBy:Prop-GroupBy:Select-DayOfMonth' => '%1$s (jour du mois)',
'UI:DashletGroupBy:MissingGroupBy' => 'Veuillez sélectionner le champ sur lequel les objets seront groupés',
'UI:DashletGroupByPie:Label' => 'Secteurs',
'UI:DashletGroupByPie:Description' => 'Graphique à secteur',
'UI:DashletGroupByBars:Label' => 'Barres',
'UI:DashletGroupByBars:Description' => 'Graphique en Barres',
'UI:DashletGroupByTable:Label' => 'Table',
'UI:DashletGroupByTable:Description' => 'Table',
'UI:DashletHeaderStatic:Label' => 'En-tête',
'UI:DashletHeaderStatic:Description' => 'En-tête présenté comme une barre horizontale',
'UI:DashletHeaderStatic:Prop-Title' => 'Titre',
'UI:DashletHeaderStatic:Prop-Title:Default' => 'Contacts',
'UI:DashletHeaderStatic:Prop-Icon' => 'Icône',
'UI:DashletHeaderDynamic:Label' => 'En-tête dynamique',
'UI:DashletHeaderDynamic:Description' => 'En-tête avec statistiques (regroupements)',
'UI:DashletHeaderDynamic:Prop-Title' => 'Titre',
'UI:DashletHeaderDynamic:Prop-Title:Default' => 'Contacts',
'UI:DashletHeaderDynamic:Prop-Icon' => 'Icône',
'UI:DashletHeaderDynamic:Prop-Subtitle' => 'Sous-titre',
'UI:DashletHeaderDynamic:Prop-Subtitle:Default' => 'Contacts',
'UI:DashletHeaderDynamic:Prop-Query' => 'Requête OQL',
'UI:DashletHeaderDynamic:Prop-GroupBy' => 'Grouper par',
'UI:DashletHeaderDynamic:Prop-Values' => 'Valeurs',
'UI:DashletBadge:Label' => 'Badge',
'UI:DashletBadge:Description' => 'Icône représentant une classe d\'objets, ainsi que des liens pour créer/rechercher',
'UI:DashletBadge:Prop-Class' => 'Classe',
'DayOfWeek-Sunday' => 'Dimanche',
'DayOfWeek-Monday' => 'Lundi',
'DayOfWeek-Tuesday' => 'Mardi',
'DayOfWeek-Wednesday' => 'Mercredi',
'DayOfWeek-Thursday' => 'Jeudi',
'DayOfWeek-Friday' => 'Vendredi',
'DayOfWeek-Saturday' => 'Samedi',
));
?>

View File

@@ -39,11 +39,15 @@ $(function()
{
if (this.bModified)
{
this.element.find(".prop_icon span.ui-icon").css({visibility: ''});
this.element.addClass("itop-property-field-modified");
this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: ''});
this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: ''});
}
else
{
this.element.find(".prop_icon span.ui-icon").css({visibility: 'hidden'});
this.element.removeClass("itop-property-field-modified");
this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: 'hidden'});
this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: 'hidden'});
}
},
@@ -52,6 +56,7 @@ $(function()
_destroy: function()
{
this.element.removeClass( "itop-property-field" );
this.element.removeClass("itop-property-field-modified");
},
// _setOptions is called with a hash of all options that are changing
@@ -211,13 +216,13 @@ function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId)
}
if (!bValid)
{
$('#v_'+sFieldId).html('<img style="vertical-align:middle;" src="'+GetAbsoluteUrlAppRoot()+'images/validation_error.png">');
$('#v_'+sFieldId).addClass('ui-state-error');
if (oFormValidation[sFormId] == undefined) oFormValidation[sFormId] = [];
oFormValidation[sFormId].push(sFieldId);
}
else
{
$('#v_'+sFieldId).html('');
$('#v_'+sFieldId).removeClass('ui-state-error');
}
}

View File

@@ -2159,6 +2159,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
default: // Menu node rendering (templates)
ApplicationMenu::LoadAdditionalMenus();
$oMenuNode = ApplicationMenu::GetMenuNode(ApplicationMenu::GetMenuIndexById(ApplicationMenu::GetActiveNodeId()));
if (is_object($oMenuNode))
{

View File

@@ -672,18 +672,7 @@ try
case 'dashboard_editor':
$sId = utils::ReadParam('id', '', false, 'raw_data');
// Before searching for the menus make sure that all of them exist
// Build menus from module handlers
//
foreach(get_declared_classes() as $sPHPClass)
{
if (is_subclass_of($sPHPClass, 'ModuleHandlerAPI'))
{
$aCallSpec = array($sPHPClass, 'OnMenuCreation');
call_user_func($aCallSpec);
}
}
ApplicationMenu::LoadAdditionalMenus();
$idx = ApplicationMenu::GetMenuIndexById($sId);
$oMenu = ApplicationMenu::GetMenuNode($idx);
$oMenu->RenderEditor($oPage);
@@ -808,7 +797,7 @@ try
break;
case 'add_dashlet':
$oForm = RuntimeDashboard::GetDashletCreationForm('');
$oForm = RuntimeDashboard::GetDashletCreationForm();
$aValues = $oForm->ReadParams();
$sDashletClass = $aValues['dashlet_class'];
@@ -819,6 +808,7 @@ try
$oDashlet = new $sDashletClass(0);
$oDashlet->FromParams($aValues);
ApplicationMenu::LoadAdditionalMenus();
$index = ApplicationMenu::GetMenuIndexById($sMenuId);
$oMenu = ApplicationMenu::GetMenuNode($index);
$oMenu->AddDashlet($oDashlet);