浏览代码

#780 Auto refresh for the dashboards (+ cosmetics changes for the shortcuts)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2929 a333f486-631f-4898-b8df-5754b55c2be0
romainq 11 年之前
父节点
当前提交
ab43672029

+ 106 - 29
application/dashboard.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -29,6 +29,8 @@ require_once(APPROOT.'core/modelreflection.class.inc.php');
 abstract class Dashboard
 {
 	protected $sTitle;
+	protected $bAutoReload;
+	protected $iAutoReloadSec;
 	protected $sLayoutClass;
 	protected $aWidgetsData;
 	protected $oDOMNode;
@@ -38,7 +40,10 @@ abstract class Dashboard
 	
 	public function __construct($sId)
 	{
+		$this->sTitle = '';
 		$this->sLayoutClass = 'DashboardLayoutOneCol';
+		$this->bAutoReload = false;
+		$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
 		$this->aCells = array();
 		$this->oDOMNode = null;
 		$this->sId = $sId;
@@ -76,6 +81,20 @@ abstract class Dashboard
 			$this->sTitle = '';
 		}
 		
+		$this->bAutoReload = false;
+		$this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
+		if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0))
+		{
+			if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0))
+			{
+				$this->bAutoReload = ($oAutoReloadEnabled->textContent == 'true');
+			}
+			if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0))
+			{
+				$this->iAutoReloadSec = max(5, (int)$oAutoReloadInterval->textContent);
+			}
+		}
+
 		if ($oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0))
 		{
 			$oCellsList = $oCellsNode->getElementsByTagName('cell');
@@ -173,6 +192,13 @@ abstract class Dashboard
 		$oNode = $oDoc->createElement('title', $this->sTitle);
 		$oDefinition->appendChild($oNode);
 
+		$oAutoReloadNode = $oDoc->createElement('auto_reload');
+		$oDefinition->appendChild($oAutoReloadNode);
+		$oNode = $oDoc->createElement('enabled', $this->bAutoReload ? 'true' : 'false');
+		$oAutoReloadNode->appendChild($oNode);
+		$oNode = $oDoc->createElement('interval', $this->iAutoReloadSec);
+		$oAutoReloadNode->appendChild($oNode);
+
 		$oCellsNode = $oDoc->createElement('cells');
 		$oDefinition->appendChild($oCellsNode);
 		
@@ -208,6 +234,8 @@ abstract class Dashboard
 	{
 		$this->sLayoutClass = $aParams['layout_class'];
 		$this->sTitle = $aParams['title'];
+		$this->bAutoReload = $aParams['auto_reload'] == 'true';
+		$this->iAutoReloadSec = max(5, (int) $aParams['auto_reload_sec']);
 		
 		foreach($aParams['cells'] as $aCell)
 		{
@@ -249,12 +277,32 @@ abstract class Dashboard
 	{
 		return $this->sTitle;
 	}
-	
+
 	public function SetTitle($sTitle)
 	{
 		$this->sTitle = $sTitle;
 	}
-		
+
+	public function GetAutoReload()
+	{
+		return $this->bAutoReload;
+	}
+
+	public function SetAutoReload($bAutoReload)
+	{
+		$this->bAutoReload = $bAutoReload;
+	}
+
+	public function GetAutoReloadInterval()
+	{
+		return $this->iAutoReloadSec;
+	}
+
+	public function SetAutoReloadInterval($iAutoReloadSec)
+	{
+		$this->iAutoReloadSec = max(5, (int)$iAutoReloadSec);
+	}
+
 	public function AddDashlet($oDashlet)
 	{
 		$sId = $this->GetNewDashletId();
@@ -305,12 +353,30 @@ abstract class Dashboard
 
 		$oField = new DesignerLongTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
 		$oForm->AddField($oField);
+
+		$oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload);
+		$oForm->AddField($oField);
+
+		$oField = new DesignerTextField('auto_reload_sec', Dict::S('UI:DashboardEdit:AutoReloadSec'), $this->iAutoReloadSec);
+		$oField->SetValidationPattern('^$|^0*([5-9]|[1-9][0-9]+)$'); // Can be empty, or a number > 4
+		$oForm->AddField($oField);
+
 		$this->SetFormParams($oForm);
 		$oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');	
-		
+
 		$oPage->add('</div>');
+
+		$sRateTitle = addslashes(Dict::S('UI:DashboardEdit:AutoReloadSec+'));
 		$oPage->add_ready_script(
 <<<EOF
+	// Note: the title gets deleted by the validation mechanism
+	$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
+	$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
+	
+	$('#attr_auto_reload').change( function(ev) {
+		$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
+	} );
+
 	$('#select_layout').buttonset();
 	$('#select_dashlet').droppable({
 		accept: '.dashlet',
@@ -477,37 +543,34 @@ class RuntimeDashboard extends Dashboard
 		}
 	}
 	
-	public function Render($oPage, $bEditMode = false, $aExtraParams = array())
+	public function RenderEditionTools($oPage)
 	{
-		parent::Render($oPage, $bEditMode, $aExtraParams);
-		if (!$bEditMode)
-		{
-			$sEditMenu = "<td><span id=\"DashboardMenu\"><ul><li><img src=\"../images/edit.png\"><ul>";
-		
-			$aActions = array();
-			$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}')");
-			$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
+		$sEditMenu = "<td><span id=\"DashboardMenu\"><ul><li><img src=\"../images/edit.png\"><ul>";
+	
+		$aActions = array();
+		$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}')");
+		$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
 
-			if ($this->bCustomized)
-			{
-				$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
-												"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}'); else return false");
-				$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
-			}
-			utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
-			$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
-					
+		if ($this->bCustomized)
+		{
+			$oRevert = new JSPopupMenuItem('UI:Dashboard:RevertConfirm', Dict::S('UI:Dashboard:Revert'),
+											"if (confirm('".addslashes(Dict::S('UI:Dashboard:RevertConfirm'))."')) return RevertDashboard('{$this->sId}'); else return false");
+			$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
+		}
+		utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);
+		$sEditMenu .= $oPage->RenderPopupMenuItems($aActions);
+				
 
-			$sEditMenu = addslashes($sEditMenu);
-			//$sEditBtn = addslashes('<div style="display: inline-block; height: 55px; width:200px;vertical-align:center;line-height:60px;text-align:left;"><button onclick="EditDashboard(\''.$this->sId.'\');">Edit This Page</button></div>');
-			$oPage->add_ready_script(
+		$sEditMenu = addslashes($sEditMenu);
+		//$sEditBtn = addslashes('<div style="display: inline-block; height: 55px; width:200px;vertical-align:center;line-height:60px;text-align:left;"><button onclick="EditDashboard(\''.$this->sId.'\');">Edit This Page</button></div>');
+		$oPage->add_ready_script(
 <<<EOF
 	$('#logOffBtn').parent().before('$sEditMenu');
 	$('#DashboardMenu>ul').popupmenu();
 	
 EOF
-			);
-			$oPage->add_script(
+		);
+		$oPage->add_script(
 <<<EOF
 function EditDashboard(sId)
 {
@@ -530,8 +593,7 @@ function RevertDashboard(sId)
 	return false;
 }
 EOF
-			);
-		}
+		);
 	}
 
 	public function RenderProperties($oPage)
@@ -550,6 +612,18 @@ EOF
 			return true;
 		}
 	});
+	$('#row_attr_auto_reload').property_field('option', {parent_selector: '.itop-dashboard', auto_apply: true, 'do_apply': function() {
+			var bAutoReload = $('#attr_auto_reload').is(':checked');
+			$('.itop-dashboard').runtimedashboard('option', {auto_reload: bAutoReload});
+			return true;
+		}
+	});
+	$('#row_attr_auto_reload_sec').property_field('option', {parent_selector: '.itop-dashboard', auto_apply: true, 'do_apply': function() {
+			var iAutoReloadSec = $('#attr_auto_reload_sec').val();
+			$('.itop-dashboard').runtimedashboard('option', {auto_reload_sec: iAutoReloadSec});
+			return true;
+		}
+	});
 EOF
 		);
 	}
@@ -575,6 +649,8 @@ EOF
 		
 		$sId = addslashes($this->sId);
 		$sLayoutClass = addslashes($this->sLayoutClass);
+		$sAutoReload = $this->bAutoReload ? 'true' : 'false';
+		$sAutoReloadSec = (string) $this->iAutoReloadSec;
 		$sTitle = addslashes($this->sTitle);
 		$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
 
@@ -627,6 +703,7 @@ $('#dashboard_editor').dialog({
 
 $('#dashboard_editor .ui-layout-center').runtimedashboard({
 	dashboard_id: '$sId', layout_class: '$sLayoutClass', title: '$sTitle',
+	auto_reload: $sAutoReload, auto_reload_sec: $sAutoReloadSec,
 	submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard'},
 	render_to: '$sUrl', render_parameters: {operation: 'render_dashboard'},
 	new_dashlet_parameters: {operation: 'new_dashlet'}

+ 1 - 1
application/displayblock.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //

+ 35 - 2
application/menunode.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -879,8 +879,41 @@ class DashboardMenuNode extends MenuNode
 		$oDashboard = $this->GetDashboard();
 		if ($oDashboard != null)
 		{
+			$sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $this->sMenuId);
+			$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
 			$oDashboard->Render($oPage, false, $aExtraParams);
-			
+			$oPage->add('</div>');
+			$oDashboard->RenderEditionTools($oPage);
+
+			if ($oDashboard->GetAutoReload())
+			{
+				$sId = $this->sMenuId;
+				$sExtraParams = json_encode($aExtraParams);
+				$iReloadInterval = 1000 * $oDashboard->GetAutoReloadInterval();
+				$oPage->add_script(
+<<<EOF
+					setInterval("ReloadDashboard('$sDivId');", $iReloadInterval);
+
+					function ReloadDashboard(sDivId)
+					{
+						var oExtraParams = $sExtraParams;
+						// Do not reload when a dialog box is active
+						if (!($('.ui-dialog:visible').length > 0))
+						{
+							$('.dashboard_contents#'+sDivId).block();
+							$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
+							   { operation: 'reload_dashboard', dashboard_id: '$sId', extra_params: oExtraParams},
+							   function(data){
+								 $('.dashboard_contents#'+sDivId).html(data);
+								 $('.dashboard_contents#'+sDivId).unblock();
+								}
+							 );
+						}
+					}
+EOF
+				);
+			}
+
 			$bEdit = utils::ReadParam('edit', false);
 			if ($bEdit)
 			{

+ 4 - 3
application/shortcut.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -277,8 +277,9 @@ class ShortcutOQL extends Shortcut
 		$oPage->add_ready_script(
 <<<EOF
 
-$("#attr_auto_reload_sec").attr('title', '$sRateTitle');
-$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
+// Note: the title gets deleted by the validation mechanism
+$("#attr_auto_reload_sec").tooltip({items: 'input', content: '$sRateTitle'});
+$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
 
 $('#attr_auto_reload').change( function(ev) {
 	$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));

+ 5 - 1
dictionaries/dictionary.itop.ui.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -1081,6 +1081,10 @@ When associated with a trigger, each action is given an "order" number, specifyi
 
 	'UI:DashboardEdit:Title' => 'Dashboard Editor',
 	'UI:DashboardEdit:DashboardTitle' => 'Title',
+	'UI:DashboardEdit:AutoReload' => 'Automatic refresh',
+	'UI:DashboardEdit:AutoReloadSec' => 'Automatic refresh interval (seconds)',
+	'UI:DashboardEdit:AutoReloadSec+' => 'The minimum allowed is 5 seconds',
+
 	'UI:DashboardEdit:Layout' => 'Layout',
 	'UI:DashboardEdit:Properties' => 'Dashboard Properties',
 	'UI:DashboardEdit:Dashlets' => 'Available Dashlets',	

+ 10 - 1
dictionaries/fr.dictionary.itop.ui.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -923,6 +923,9 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 
 	'UI:DashboardEdit:Title' => 'Editeur de tableau de bord',
 	'UI:DashboardEdit:DashboardTitle' => 'Titre',
+	'UI:DashboardEdit:AutoReload' => 'Réactualisation automatique',
+	'UI:DashboardEdit:AutoReloadSec' => 'Réactualisation toutes les (secondes)',
+	'UI:DashboardEdit:AutoReloadSec+' => 'Le minimum permis est de 5 secondes',
 	'UI:DashboardEdit:Layout' => 'Mise en page',
 	'UI:DashboardEdit:Properties' => 'Propriétés du tableau de bord',
 	'UI:DashboardEdit:Dashlets' => 'Indicateurs',	
@@ -1017,6 +1020,12 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 	'Class:ShortcutOQL+' => '',
 	'Class:ShortcutOQL/Attribute:oql' => 'Requête',
 	'Class:ShortcutOQL/Attribute:oql+' => 'Requête de définition de l\'ensemble des objets',
+	'Class:ShortcutOQL/Attribute:auto_reload' => 'Réactualisation automatique',
+	'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Désactivée',
+	'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Personnalisée',
+	'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Réactualisation toutes les (secondes)',
+	'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'Le minimum permis est de 5 secondes',
+
 	'UI:FillAllMandatoryFields' => 'Veuillez remplir tous les champs obligatoires.',
 	
 	'UI:CSVImportConfirmTitle' => 'Veuillez confirmer cette opération',

+ 16 - 1
js/dashboard.js

@@ -16,6 +16,8 @@ $(function()
 			dashboard_id: '',
 			layout_class: '',
 			title: '',
+			auto_reload: false,
+			auto_reload_sec: 300,
 			submit_to: 'index.php',
 			submit_parameters: {},
 			render_to: 'index.php',
@@ -92,6 +94,8 @@ $(function()
 			oState.dashboard_id = this.options.dashboard_id;
 			oState.layout_class = this.options.layout_class;
 			oState.title = this.options.title;
+			oState.auto_reload = this.options.auto_reload;
+			oState.auto_reload_sec = this.options.auto_reload_sec;
 			
 			return oState;
 		},
@@ -206,6 +210,8 @@ $(function()
 			dashboard_id: '',
 			layout_class: '',
 			title: '',
+			auto_reload: '',
+			auto_reload_sec: '',
 			submit_to: 'index.php',
 			submit_parameters: {},
 			render_to: 'index.php',
@@ -239,13 +245,22 @@ $(function()
 		// _setOptions is called with a hash of all options that are changing
 		_setOptions: function()
 		{
+			this.bRefreshNeeded = false;
+
 			this._superApply(arguments);
-			this._refresh();
+			if (this.bRefreshNeeded)
+			{
+				this._refresh();
+			}
 		},
 		// _setOption is called for each individual option that is changing
 		_setOption: function( key, value )
 		{
 			this._superApply(arguments);
+			if ((key != 'auto_reload') && (key != 'auto_reload_sec'))
+			{
+				this.bRefreshNeeded = true;
+			}
 		},
 		// called when created, and later when changing options
 		_refresh: function()

+ 17 - 3
pages/ajax.render.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -784,7 +784,17 @@ try
 		{
 			$oExtensionInstance->OnFormCancel($sTempId);
 		}
-		
+		break;
+
+		case 'reload_dashboard':
+		$oPage->SetContentType('text/html');
+		$sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data');
+		$aExtraParams = utils::ReadParam('extra_params', '', false, 'raw_data');
+		ApplicationMenu::LoadAdditionalMenus();
+		$idx = ApplicationMenu::GetMenuIndexById($sDashboardId);
+		$oMenu = ApplicationMenu::GetMenuNode($idx);
+		$oDashboard = $oMenu->GetDashboard();
+		$oDashboard->Render($oPage, false, $aExtraParams);
 		break;
 		
 		case 'dashboard_editor':
@@ -879,6 +889,8 @@ try
 		$aParams = array();
 		$aParams['layout_class'] = utils::ReadParam('layout_class', '');
 		$aParams['title'] = utils::ReadParam('title', '', false, 'raw_data');
+		$aParams['auto_reload'] = utils::ReadParam('auto_reload', false);
+		$aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300);
 		$aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data');
 		$oDashboard = new RuntimeDashboard($sDashboardId);
 		$oDashboard->FromParams($aParams);
@@ -910,6 +922,8 @@ EOF
 		$aParams['layout_class'] = utils::ReadParam('layout_class', '');
 		$aParams['title'] = utils::ReadParam('title', '', false, 'raw_data');
 		$aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data');
+		$aParams['auto_reload'] = utils::ReadParam('auto_reload', false);
+		$aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300);
 		$oDashboard = new RuntimeDashboard($sDashboardId);
 		$oDashboard->FromParams($aParams);
 		$oDashboard->Render($oPage, true /* bEditMode */);
@@ -919,7 +933,7 @@ EOF
 		$sOQL = utils::ReadParam('oql', '', false, 'raw_data');
 		RuntimeDashboard::GetDashletCreationDlgFromOQL($oPage, $sOQL);
 		break;
-		
+
 		case 'add_dashlet':
 		$oForm = RuntimeDashboard::GetDashletCreationForm();
 		$aValues = $oForm->ReadParams();