From ef59badf5b5ccea73e595479c3b4f3e34b5d0c50 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Sat, 29 Sep 2012 16:03:16 +0000 Subject: [PATCH] Implementation of a new extension "iPopupMenuExtension" to allow a module to add menu items almost anywhere inside iTop. SVN:trunk[2220] --- application/applicationextension.inc.php | 146 +++++++++++++++++- application/dashboard.class.inc.php | 32 +++- application/datatable.class.inc.php | 15 +- application/displayblock.class.inc.php | 139 +++++++++++++---- application/itopwebpage.class.inc.php | 16 +- application/menunode.class.inc.php | 2 +- application/utils.inc.php | 21 +++ application/webpage.class.inc.php | 31 ++++ .../itop-attachments/main.attachments.php | 1 - dictionaries/dictionary.itop.ui.php | 5 + dictionaries/fr.dictionary.itop.ui.php | 4 + js/dashboard.js | 122 ++++++++++++++- pages/ajax.render.php | 50 ++++++ 13 files changed, 535 insertions(+), 49 deletions(-) diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index 209f1424c..37921b0c7 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -1,5 +1,5 @@ +/** + * New extension to add menu items in the "popup" menus inside iTop. Provides a greater flexibility than + * iApplicationUIExtension::EnumAllowedActions. + * + * To add some menus into iTop, declare a class that implements this interface, it will be called automatically + * by the application, as long as the class definition is included somewhere in the code + */ +interface iPopupMenuExtension +{ + // Possible types of menu into which new items can be added + const MENU_OBJLIST_ACTIONS = 1; // $param is a DBObjectSet containing the list of objects + const MENU_OBJLIST_TOOLKIT = 2; // $param is a DBObjectSet containing the list of objects + const MENU_OBJDETAILS_ACTIONS = 3; // $param is a DBObject instance: the object currently displayed + const MENU_DASHBOARD_ACTIONS = 4; // $param is a Dashboard instance: the dashboard currently displayed + const MENU_USER_ACTIONS = 5; // $param is a null ?? + + /** + * Get the list of items to be added to a menu. The items will be inserted in the menu in the order of the returned array + * @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx above + * @param mixed $param Depends on $iMenuId, see the constants defined above + * @return Array An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu + */ + public static function EnumItems($iMenuId, $param); +} + +/** + * Each menu items is defined by an instance of an object derived from the class + * ApplicationPopupMenu below + * + */ +abstract class ApplicationPopupMenuItem +{ + protected $sUID; + protected $sLabel; + + public function __construct($sUID, $sLabel) + { + $this->sUID = $sUID; + $this->sLabel = $sLabel; + } + + public function GetUID() + { + return $this->sUID; + } + + public function GetLabel() + { + return $this->sLabel; + } + + /** + * Returns the components to create a popup menu item in HTML + * @return Hash A hash array: array('label' => , 'url' => , 'target' => , 'onclick' => ) + */ + abstract public function GetMenuItem(); + + public function GetLinkedScripts() + { + return array(); + } +} + +/** + * Class for adding an item into a popup menu that browses to the given URL + */ +class URLPopupMenuItem extends ApplicationPopupMenuItem +{ + protected $sURL; + protected $sTarget; + + /** + * Class for adding an item that browses to the given URL + * @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough + * @param string $sLabel The display label of the menu (must be localized) + * @param string $sURL If the menu is an hyperlink, provide the absolute hyperlink here + * @param string $sTarget In case the menu is an hyperlink and a specific target is needed (_blank for example), pass it here + */ + public function __construct($sUID, $sLabel, $sURL, $sTarget = '_top') + { + parent::__construct($sUID, $sLabel); + $this->sURL = $sURL; + $this->sTarget = $sTarget; + } + + public function GetMenuItem() + { + return array ('label' => $this->GetLabel(), 'url' => $this->sURL, 'target' => $this->sTarget); + } +} + +/** + * Class for adding an item into a popup menu that triggers some Javascript code + */ +class JSPopupMenuItem extends ApplicationPopupMenuItem +{ + protected $sJSCode; + protected $aIncludeJSFiles; + + /** + * Class for adding an item that triggers some Javascript code + * @param string $sUID The unique identifier of this menu in iTop... make sure you pass something unique enough + * @param string $sLabel The display label of the menu (must be localized) + * @param string $sJSCode In case the menu consists in executing some havascript code inside the page, pass it here. If supplied $sURL ans $sTarget will be ignored + * @param array $aIncludeJSFiles An array of file URLs to be included (once) to provide some JS libraries for the page. + */ + public function __construct($sUID, $sLabel, $sJSCode, $aIncludeJSFiles = array()) + { + parent::__construct($sUID, $sLabel); + $this->sJSCode = $sJSCode; + $this->aIncludeJSFiles = $aIncludeJSFiles; + } + + public function GetMenuItem() + { + return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode, 'url' => '#'); + } + + public function GetLinkedScripts() + { + return $this->aIncludeJSFiles; + } +} + +/** + * Class for adding a separator (horizontal line, not selectable) the output + * will automatically reduce several consecutive separators to just one + */ +class SeparatorPopupMenuItem extends ApplicationPopupMenuItem +{ + /** + * Class for inserting a separator into a popup menu + */ + public function __construct() + { + parent::__construct('', ''); + } + + public function GetMenuItem() + { + return array ('label' => '', 'url' => ''); + } +} diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index a97843c51..0b92ff214 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -40,8 +40,11 @@ abstract class Dashboard public function FromXml($sXml) { + $this->aCells = array(); // reset the content of the dashboard + set_error_handler(array('Dashboard', 'ErrorHandler')); $oDoc = new DOMDocument(); $oDoc->loadXML($sXml); + restore_error_handler(); $this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0); $oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0); @@ -68,6 +71,21 @@ abstract class Dashboard } } + /** + * Error handler to turn XML loading warnings into exceptions + */ + public static function ErrorHandler($errno, $errstr, $errfile, $errline) + { + if ($errno == E_WARNING && (substr_count($errstr,"DOMDocument::loadXML()")>0)) + { + throw new DOMException($errstr); + } + else + { + return false; + } + } + public function ToXml() { $oDoc = new DOMDocument(); @@ -365,13 +383,21 @@ class RuntimeDashboard extends Dashboard if (!$bEditMode) { $sEditMenu = ""; + utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions); + $sEditMenu .= $oPage->RenderPopupMenuItems($aActions); + + $sEditMenu = addslashes($sEditMenu); //$sEditBtn = addslashes('
'); $oPage->add_ready_script( diff --git a/application/datatable.class.inc.php b/application/datatable.class.inc.php index ba4f0d0e1..44bd7e3c8 100644 --- a/application/datatable.class.inc.php +++ b/application/datatable.class.inc.php @@ -21,10 +21,11 @@ * @author Denis Flaven * @license http://www.opensource.org/licenses/gpl-3.0.html GPL */ + class DataTable { protected $iListId; // Unique ID inside the web page - protected $sTableId; // identifier for sqve the settings (combined with the class aliases) + protected $sTableId; // identifier for saving the settings (combined with the class aliases) protected $oSet; // The set of objects to display protected $aClassAliases; // The aliases (alias => class) inside the set protected $iNbObjects; // Total number of objects inthe set @@ -250,8 +251,16 @@ EOF; protected function GetToolkitMenu(WebPage $oPage, $aExtraParams) { $sMenuTitle = Dict::S('UI:ConfigureThisList'); - $sHtml = ''; - //$oPage->add_ready_script("$('#tk_{$this->iListId} > ul').popupmenu();"); + $sHtml = '
    • '; + + $oMenuItem1 = new JSPopupMenuItem('iTop::ConfigureList', $sMenuTitle, "$('#datatable_dlg_".$this->iListId."').dialog('open');"); + $aActions = array( + $oMenuItem1->GetUID() => $oMenuItem1->GetMenuItem(), + ); + $this->oSet->Rewind(); + utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_OBJLIST_TOOLKIT, $this->oSet, $aActions); + $this->oSet->Rewind(); + $sHtml .= $oPage->RenderPopupMenuItems($aActions); return $sHtml; } diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index 3ed4cd850..964e93d82 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -1359,7 +1359,7 @@ class MenuBlock extends DisplayBlock { // New plugins can provide javascript handlers via the 'onclick' property //TODO: enable extension of different menus by checking the 'target' property ?? - $aActions[$sLabel] = array ('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'url' => isset($data['onclick']) ? $data['onclick'] : ''); + $aActions[$sLabel] = array ('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : ''); } else { @@ -1368,6 +1368,24 @@ class MenuBlock extends DisplayBlock } } } + + // New extensions based on iPopupMenuItem interface + switch($this->m_sStyle) + { + case 'list': + $oSet->Rewind(); + $param = $oSet; + $iMenuId = iPopupMenuExtension::MENU_OBJLIST_ACTIONS; + break; + + case 'details': + $oSet->Rewind(); + $param = $oSet->Fetch(); + $iMenuId = iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS; + break; + + } + utils::GetPopupMenuItems($oPage, $iMenuId, $param, $aActions); } $aFavoriteActions = array(); $aCallSpec = array($sClass, 'GetShortcutActions'); @@ -1395,38 +1413,10 @@ class MenuBlock extends DisplayBlock else { $sHtml .= "
        \n
      • ".Dict::S('UI:Menu:Actions')."\n
          \n"; - } - $sPrevUrl = ''; - foreach ($aActions as $key => $aAction) - { - if (in_array($key, $aShortcutActions)) - { - $aFavoriteActions[] = $aAction; - } - else - { - $sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : ""; - $sOnClick = isset($aAction['onclick']) ? " onclick=\"{$aAction['onclick']}\"" : ""; - if (empty($aAction['url'])) - { - if ($sPrevUrl != '') // Don't output consecutively two separators... - { - $sHtml .= "
        • {$aAction['label']}
        • \n"; - } - $sPrevUrl = ''; - } - else - { - $sHtml .= "
        • {$aAction['label']}
        • \n"; - $sPrevUrl = $aAction['url']; - } - } - } - $sHtml .= "
        \n
      • \n
      "; - foreach(array_reverse($aFavoriteActions) as $aAction) - { - $sHtml .= ""; } + + $sHtml .= $oPage->RenderPopupMenuItems($aActions, $aFavoriteActions); + static $bPopupScript = false; if (!$bPopupScript) { @@ -1456,4 +1446,87 @@ class MenuBlock extends DisplayBlock } } } -?> + +/** + * Some dummy menus for testing + */ +class ExtraMenus implements iPopupMenuExtension +{ + /* + const MENU_OBJLIST_ACTIONS = 1; // $param is a DBObjectSet containing the list of objects + const MENU_OBJLIST_TOOLKIT = 2; // $param is a DBObjectSet containing the list of objects + const MENU_OBJDETAILS_ACTIONS = 3; // $param is a DBObject instance: the object currently displayed + const MENU_DASHBOARD_ACTIONS = 4; // $param is a Dashboard instance: the dashboard currently displayed + const MENU_USER_ACTIONS = 5; // $param is a null ?? + */ + + /** + * Get the list of items to be added to a menu. The items will be inserted in the menu in the order of the returned array + * @param int $iMenuId The identifier of the type of menu, as listed by the constants MENU_xxx above + * @param mixed $param Depends on $iMenuId see the constants define above + * @return Array An array of ApplicationPopupMenuItem or an empty array if no action is to be added to the menu + */ + public static function EnumItems($iMenuId, $param) + { + switch($iMenuId) + { + /* + case iPopupMenuExtension::MENU_OBJLIST_ACTIONS: + // $param is a DBObjectSet + $aResult = array( + new JSPopupMenuItem('Test::Item1', 'List Test 1', "alert('Test 1')"), + new JSPopupMenuItem('Test::Item2', 'List Test 2', "alert('Test 2')"), + ); + break; + + case iPopupMenuExtension::MENU_OBJLIST_TOOLKIT: + // $param is a DBObjectSet + $aResult = array( + new JSPopupMenuItem('Test::Item1', 'Toolkit Test 1', "alert('Test 1')"), + new JSPopupMenuItem('Test::Item2', 'Toolkit Test 2', "alert('Test 2')"), + ); + break; + + case iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS: + // $param is a DBObject + $aResult = array( + new JSPopupMenuItem('Test::Item1', 'Object Test 1', "alert('Test 1')"), + new JSPopupMenuItem('Test::Item2', 'Object Test 2', "alert('Test 2')"), + ); + break; + */ + + case iPopupMenuExtension::MENU_DASHBOARD_ACTIONS: + // $param is a Dashboard + $oAppContext = new ApplicationContext(); + $aParams = $oAppContext->GetAsHash(); + $sMenuId = ApplicationMenu::GetActiveNodeId(); + $sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle')); + $sDlgText = addslashes(Dict::S('UI:ImportDashboardText')); + $sCloseBtn = addslashes(Dict::S('UI:Button:Cancel')); + $aResult = array( + new SeparatorPopupMenuItem(), + new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sMenuId), + new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sMenuId', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn' })", + array('../js/ajaxfileupload.js')), + ); + break; + + /* + case iPopupMenuExtension::MENU_USER_ACTIONS: + // $param is null ?? + $aResult = array( + new SeparatorPopupMenuItem(), + new JSPopupMenuItem('Test::Item1', 'Reset preferences...', "alert('Test 1')"), + new JSPopupMenuItem('Test::Item2', 'Do Something Stupid', "alert('Hey Dude !')"), + ); + break; + */ + + default: + // Unknown type of menu, do nothing + $aResult = array(); + } + return $aResult; + } +} diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php index 1ce079bf5..8b35e6aa0 100644 --- a/application/itopwebpage.class.inc.php +++ b/application/itopwebpage.class.inc.php @@ -650,18 +650,24 @@ EOF } $sLogOffMenu = "
        • "; $sLogOffMenu .= "
        • $sLogonMessage
        • \n"; - $sLogOffMenu .= "
        • GetForLink()."\">".Dict::S('UI:Preferences')."
        • \n"; + $aActions = array(); + + $oPrefs = new URLPopupMenuItem('UI:Preferences', Dict::S('UI:Preferences'), utils::GetAbsoluteUrlAppRoot()."pages/preferences.php?".$oAppContext->GetForLink()); + $aActions[$oPrefs->GetUID()] = $oPrefs->GetMenuItem(); if (utils::CanLogOff()) { - //$sLogOffMenu .= "
        • ".Dict::S('UI:LogOffMenu')."
        • \n"; - $sLogOffMenu .= "
        • ".Dict::S('UI:LogOffMenu')."
        • \n"; + $oLogOff = new URLPopupMenuItem('UI:LogOffMenu', Dict::S('UI:LogOffMenu'), utils::GetAbsoluteUrlAppRoot().'pages/logoff.php'); + $aActions[$oLogOff->GetUID()] = $oLogOff->GetMenuItem(); } if (UserRights::CanChangePassword()) { - $sLogOffMenu .= "
        • ".Dict::S('UI:ChangePwdMenu')."
        • \n"; + $oChangePwd = new URLPopupMenuItem('UI:ChangePwdMenu', Dict::S('UI:ChangePwdMenu'), utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=change_pwd'); + $aActions[$oChangePwd->GetUID()] = $oChangePwd->GetMenuItem(); } - $sLogOffMenu .= "
        \n
      • \n
      \n"; + utils::GetPopupMenuItems($this, iPopupMenuExtension::MENU_USER_ACTIONS, null, $aActions); + $sLogOffMenu .= $this->RenderPopupMenuItems($aActions); + $sRestrictions = ''; if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) diff --git a/application/menunode.class.inc.php b/application/menunode.class.inc.php index c1440de90..e7b1bbf91 100644 --- a/application/menunode.class.inc.php +++ b/application/menunode.class.inc.php @@ -812,7 +812,7 @@ class DashboardMenuNode extends MenuNode return parent::GetHyperlink($aExtraParams); } - protected function GetDashboard() + public function GetDashboard() { $sDashboardDefinition = @file_get_contents($this->sDashboardFile); if ($sDashboardDefinition !== false) diff --git a/application/utils.inc.php b/application/utils.inc.php index 25fd020b6..8533f7a45 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -768,6 +768,27 @@ class utils } } + /** + * Get the "Back" button to go out of the current environment + */ + public static function GetPopupMenuItems($oPage, $iMenuId, $param, &$aActions) + { + foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) + { + foreach($oExtensionInstance->EnumItems($iMenuId, $param) as $oMenuItem) + { + if (is_object($oMenuItem)) + { + $aActions[$oMenuItem->GetUID()] = $oMenuItem->GetMenuItem(); + + foreach($oMenuItem->GetLinkedScripts() as $sLinkedScript) + { + $oPage->add_linked_script($sLinkedScript); + } + } + } + } + } /** * Get target configuration file name (including full path) */ diff --git a/application/webpage.class.inc.php b/application/webpage.class.inc.php index b5f552c7c..38d16e656 100644 --- a/application/webpage.class.inc.php +++ b/application/webpage.class.inc.php @@ -604,5 +604,36 @@ class WebPage implements Page $this->a_OutputOptions[$sFormat][$sOptionName] = $sValue; } } + + public function RenderPopupMenuItems($aActions, $aFavoriteActions = array()) + { + $sPrevUrl = ''; + $sHtml = ''; + foreach ($aActions as $aAction) + { + $sClass = isset($aAction['class']) ? " class=\"{$aAction['class']}\"" : ""; + $sOnClick = isset($aAction['onclick']) ? " onclick=\"{$aAction['onclick']}\"" : ""; + if (empty($aAction['url'])) + { + if ($sPrevUrl != '') // Don't output consecutively two separators... + { + $sHtml .= "
    • {$aAction['label']}
    • "; + } + $sPrevUrl = ''; + } + else + { + $sHtml .= "
    • {$aAction['label']}
    • "; + $sPrevUrl = $aAction['url']; + } + } + $sHtml .= "
"; + foreach(array_reverse($aFavoriteActions) as $aAction) + { + $sHtml .= ""; + } + + return $sHtml; + } } ?> \ No newline at end of file diff --git a/datamodel/itop-attachments/main.attachments.php b/datamodel/itop-attachments/main.attachments.php index dd94643de..7b79969ed 100644 --- a/datamodel/itop-attachments/main.attachments.php +++ b/datamodel/itop-attachments/main.attachments.php @@ -356,7 +356,6 @@ EOF $oPage->add('
'); $sMaxUpload = $this->GetMaxUpload(); $oPage->p(Dict::S('Attachments:AddAttachment').' '.$sMaxUpload); - //$oPage->p(''); $oPage->p(''); $oPage->p(''); $oPage->add(''); diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index a5d70bf00..2221f7cb2 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -988,6 +988,11 @@ When associated with a trigger, each action is given an "order" number, specifyi '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:ExportDashBoard' => 'Export to a file', + 'UI:ImportDashBoard' => 'Import from a file...', + 'UI:ImportDashboardTitle' => 'Import From a File', + 'UI:ImportDashboardText' => 'Select a dashboard file to import:', + 'UI:DashletCreation:Title' => 'Create a new Dashlet', 'UI:DashletCreation:Dashboard' => 'Dashboard', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index d69dafb2e..0ee6b2230 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -832,6 +832,10 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé '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:ExportDashBoard' => 'Exporter dans un fichier', + 'UI:ImportDashBoard' => 'Importer depuis un fichier...', + 'UI:ImportDashboardTitle' => 'Importation depuis un fichier', + 'UI:ImportDashboardText' => 'Choisissez un fichier de définition de tableau de bord :', 'UI:DashletCreation:Title' => 'Créer un Indicateur', 'UI:DashletCreation:Dashboard' => 'Tableau de bord', diff --git a/js/dashboard.js b/js/dashboard.js index a8581c12a..cda3c16a8 100644 --- a/js/dashboard.js +++ b/js/dashboard.js @@ -219,4 +219,124 @@ $(function() }); } }); -}); \ No newline at end of file +}); + +function UploadDashboard(oOptions) +{ + var sFileId = 'dashboard_upload_file'; + var oDlg = $('

'+oOptions.text+'

'); + $('body').append(oDlg); + oOptions.file_id = sFileId; + + oDlg.dashboard_upload_dlg(oOptions); +} + + +//jQuery UI style "widget" for managing a "import dashboard" dialog (file upload) +$(function() +{ + // the widget definition, where "itop" is the namespace, + // "dashboard-upload-dlg" the widget name + $.widget( "itop.dashboard_upload_dlg", + { + // default options + options: + { + dashboard_id: '', + file_id: '', + text: 'Select a dashboard file to import', + title: 'Dahsboard Import', + close_btn: 'Close', + submit_to: GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=import_dashboard' + }, + + // the constructor + _create: function() + { + var me = this; + + var oButtons = {}; + oButtons[this.options.close_btn] = function() { + me.element.dialog('close'); + //me.onClose(); + }; + $('#'+this.options.file_id).bind('change', function() { me._doUpload(); } ); + this.element + .addClass('itop-dashboard_upload_dlg') + .dialog({ + modal: true, + width: 500, + height: 'auto', + title: this.options.title, + close: function() { me._onClose(); }, + buttons: oButtons + }); + }, + + // called when created, and later when changing options + _refresh: function() + { + }, + // events bound via _bind are removed automatically + // revert other modifications here + destroy: function() + { + this.element + .removeClass('itop-dashboard_upload_dlg'); + + // call the original destroy method since we overwrote it + $.Widget.prototype.destroy.call( this ); + }, + // _setOptions is called with a hash of all options that are changing + _setOptions: function() + { + // in 1.9 would use _superApply + $.Widget.prototype._setOptions.apply( this, arguments ); + this._refresh(); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + // in 1.9 would use _super + $.Widget.prototype._setOption.call( this, key, value ); + }, + _onClose: function() + { + this.element.remove(); + }, + _doUpload: function() + { + var me = this; + $.ajaxFileUpload + ( + { + url: me.options.submit_to+'&id='+me.options.dashboard_id, + secureuri:false, + fileElementId: me.options.file_id, + dataType: 'json', + success: function (data, status) + { + if(typeof(data.error) != 'undefined') + { + if(data.error != '') + { + alert(data.error); + me.element.dialog('close'); + } + else + { + me.element.dialog('close'); + location.reload(); + } + } + }, + error: function (data, status, e) + { + alert(e); + me.element.dialog('close'); + } + } + ) + } + }); +}); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 382239a0c..504529c14 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -820,6 +820,56 @@ try } break; + case 'export_dashboard': + $sMenuId = utils::ReadParam('id', ''); + ApplicationMenu::LoadAdditionalMenus(); + $index = ApplicationMenu::GetMenuIndexById($sMenuId); + $oMenu = ApplicationMenu::GetMenuNode($index); + if ($oMenu instanceof DashboardMenuNode) + { + $oDashboard = $oMenu->GetDashboard(); + $sPreviousContent = ob_get_clean(); + if (trim($sPreviousContent) != '') + { + IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n"); + } + $oPage->SetContentType('text/xml'); + $oPage->SetContentDisposition('attachment', $oMenu->GetLabel().'.xml'); + $oPage->add($oDashboard->ToXml()); + } + break; + + case 'import_dashboard': + $sMenuId = utils::ReadParam('id', ''); + ApplicationMenu::LoadAdditionalMenus(); + $index = ApplicationMenu::GetMenuIndexById($sMenuId); + $oMenu = ApplicationMenu::GetMenuNode($index); + $aResult = array('error' => ''); + try + { + if ($oMenu instanceof DashboardMenuNode) + { + $oDoc = utils::ReadPostedDocument('dashboard_upload_file'); + $oDashboard = $oMenu->GetDashboard(); + $oDashboard->FromXml($oDoc->GetData()); + $oDashboard->Save(); + } + else + { + $aResult['error'] = 'Dashboard id="'.$sMenuId.'" not found.'; + } + } + catch(DOMException $e) + { + $aResult = array('error' => Dict::S('UI:Error:InvalidDashboardFile')); + } + catch(Exception $e) + { + $aResult = array('error' => $e->getMessage()); + } + $oPage->add(json_encode($aResult)); + break; + default: $oPage->p("Invalid query."); }