mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-22 18:18:46 +02:00
Dashboards - Finalized the implementation (inc. translation in french) - still some known issues
SVN:trunk[2195]
This commit is contained in:
@@ -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');
|
||||
|
||||
|
||||
@@ -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'),
|
||||
);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -92,7 +92,9 @@ class DesignerForm
|
||||
$aRow = $oField->Render($oP, $sFormId);
|
||||
if ($oField->IsVisible())
|
||||
{
|
||||
$aDetails[] = array('label' => $aRow['label'], 'value' => $aRow['value']);
|
||||
$sValidation = ' <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"> </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"> </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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -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',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2159,6 +2159,7 @@ EOF
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
default: // Menu node rendering (templates)
|
||||
ApplicationMenu::LoadAdditionalMenus();
|
||||
$oMenuNode = ApplicationMenu::GetMenuNode(ApplicationMenu::GetMenuIndexById(ApplicationMenu::GetActiveNodeId()));
|
||||
if (is_object($oMenuNode))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user