diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 18f28b3d4..aa9632012 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -148,14 +148,10 @@ abstract class Dashboard protected function InitDashletFromDOMNode($oDomNode) { $sId = $oDomNode->getAttribute('id'); - $sClass = $oDomNode->getAttribute('xsi:type'); + $sDashletType = $oDomNode->getAttribute('xsi:type'); // Test if dashlet can be instanciated, otherwise (uninstalled, broken, ...) we display a placeholder - $sDashletType = $sClass; - if(!class_exists($sClass)) - { - $sClass = 'DashletUnknown'; - } + $sClass = static::GetDashletClassFromType($sDashletType); $oNewDashlet = new $sClass($this->oMetaModel, $sId); $oNewDashlet->SetDashletType($sDashletType); $oNewDashlet->FromDOMNode($oDomNode); @@ -516,6 +512,15 @@ EOF } abstract protected function SetFormParams($oForm); + + public static function GetDashletClassFromType($sType, $oFactory = null) + { + if (is_subclass_of($sType, 'Dashlet')) + { + return $sType; + } + return 'DashletUnknown'; + } } class RuntimeDashboard extends Dashboard diff --git a/application/dashlet.class.inc.php b/application/dashlet.class.inc.php index 453120b69..0b3237178 100644 --- a/application/dashlet.class.inc.php +++ b/application/dashlet.class.inc.php @@ -134,7 +134,14 @@ abstract class Dashlet public function FromXml($sXml) { $oDomDoc = new DOMDocument('1.0', 'UTF-8'); + libxml_clear_errors(); $oDomDoc->loadXml($sXml); + $aErrors = libxml_get_errors(); + if (count($aErrors) > 0) + { + throw new DOMException("Malformed XML"); + } + $this->FromDOMNode($oDomDoc->firstChild); } @@ -379,7 +386,6 @@ class DashletUnknown extends Dashlet { static protected $aClassList = null; - protected $sOriginalDashletClass; protected $sOriginalDashletXML; public function __construct($oModelReflection, $sId) @@ -423,8 +429,8 @@ class DashletUnknown extends Dashlet // For unknown dashlet, parameters are not parsed but passed as a raw xml if(array_key_exists('xml', $aParams)) { - // A namspace must be present for the "xsi:type" attribute, otherwise a warning will be thrown. - $sXML = ''.$aParams['xml'].''; + // A namespace must be present for the "xsi:type" attribute, otherwise a warning will be thrown. + $sXML = ''.$aParams['xml'].''; $this->FromXml($sXML); } $this->OnUpdate(); @@ -481,7 +487,7 @@ class DashletUnknown extends Dashlet if($bHasSubProperties) { $sTmp = $oDOMNode->ownerDocument->saveXML($oDOMNode, LIBXML_NOENT); - $sTmp = trim(preg_replace("/(<".$oDOMNode->tagName.".*>|<\/".$oDOMNode->tagName.">)/", "", $sTmp)); + $sTmp = trim(preg_replace("/(<".$oDOMNode->tagName."[^>]*>|<\/".$oDOMNode->tagName.">)/", "", $sTmp)); return $sTmp; } else @@ -541,13 +547,24 @@ class DashletProxy extends DashletUnknown public function Render($oPage, $bEditMode = false, $aExtraParams = array()) { // This should never be called. + $oPage->add('
'); $oPage->add('
This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.
'); + $oPage->add('
'); } public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array()) { - // TODO - $oPage->add('
RENDER NO DATA TO DO! (PREVIEW OR SO)
'); + $aInfos = static::GetInfo(); + + $sIconUrl = utils::GetAbsoluteUrlAppRoot().$aInfos['icon']; + $sExplainText = Dict::Format('UI:DashletProxy:RenderNoDataText:Edit', $this->GetDashletType()); + + $oPage->add('
'); + + $oPage->add('
'); + $oPage->add('
'.$sExplainText.'
'); + + $oPage->add('
'); } static public function GetInfo() diff --git a/css/light-grey.css b/css/light-grey.css index a1bbb635f..a906ab743 100644 --- a/css/light-grey.css +++ b/css/light-grey.css @@ -2141,12 +2141,12 @@ td.prop_icon { .dashlet-content .display_block { text-align: left; } -.dashlet-unknown .dashlet-content { +.dashlet-unknown .dashlet-content, .dashlet-proxy .dashlet-content { padding: 8px; background-color: #f2f2f2; text-align: center; } -.dashlet-unknown .dashlet-content .dashlet-ukn-text { +.dashlet-unknown .dashlet-content .dashlet-ukn-text, .dashlet-proxy .dashlet-content .dashlet-ukn-text, .dashlet-unknown .dashlet-content .dashlet-pxy-text, .dashlet-proxy .dashlet-content .dashlet-pxy-text { margin-top: 10px; } .prop_apply .ui-icon-alert { diff --git a/css/light-grey.scss b/css/light-grey.scss index 0167aa710..057fa7a78 100644 --- a/css/light-grey.scss +++ b/css/light-grey.scss @@ -2464,13 +2464,13 @@ td.prop_icon { .dashlet-content .display_block { text-align:left; } -.dashlet-unknown { +.dashlet-unknown, .dashlet-proxy { .dashlet-content { padding: 8px; background-color: #F2F2F2; text-align: center; - .dashlet-ukn-text { + .dashlet-ukn-text, .dashlet-pxy-text { margin-top: 10px; } } diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php index 17b3495d1..2d50bb618 100644 --- a/dictionaries/en.dictionary.itop.ui.php +++ b/dictionaries/en.dictionary.itop.ui.php @@ -478,7 +478,6 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:Menu:BulkDelete' => 'Delete...', 'UI:UndefinedObject' => 'undefined', 'UI:Document:OpenInNewWindow:Download' => 'Open in new window: %1$s, Download: %2$s', - 'UI:SelectAllToggle+' => 'Select / Deselect All', 'UI:SplitDateTime-Date' => 'date', 'UI:SplitDateTime-Time' => 'time', 'UI:TruncatedResults' => '%1$d objects displayed out of %2$d', @@ -1183,6 +1182,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:DashletProxy:Label' => 'Proxy', 'UI:DashletProxy:Description' => 'Proxy dashlet', + 'UI:DashletProxy:RenderNoDataText:Edit' => 'No preview available for this third-party dashlet (class "%1$s").', 'UI:DashletProxy:Prop-XMLConfiguration' => 'Configuration (shown as raw XML)', 'UI:DashletPlainText:Label' => 'Text', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 1e61dff59..dd243025c 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -1023,6 +1023,18 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'UI:Form:Property' => 'Propriété', 'UI:Form:Value' => 'Valeur', + 'UI:DashletUnknown:Label' => 'Inconnu', + 'UI:DashletUnknown:Description' => 'Element inconnu (est peut-être désinstallé)', + 'UI:DashletUnknown:RenderText:View' => 'Impossible d\'effectuer le rendu de cet élément.', + 'UI:DashletUnknown:RenderText:Edit' => 'Impossible d\'effectuer le rendu de cet élément (classe "%1$s"). Vérifiez avec votre administrateur si il est toujours disponible.', + 'UI:DashletUnknown:RenderNoDataText:Edit' => 'Impossible d\'effectuer le rendu de cet élément (classe "%1$s").', + 'UI:DashletUnknown:Prop-XMLConfiguration' => 'Configuration (XML)', + + 'UI:DashletProxy:Label' => 'Proxy', + 'UI:DashletProxy:Description' => 'Proxy', + 'UI:DashletProxy:RenderNoDataText:Edit' => 'Impossible d\'effectuer le rendu de cet élément externe (classe "%1$s").', + 'UI:DashletProxy:Prop-XMLConfiguration' => 'Configuration (XML)', + 'UI:DashletPlainText:Label' => 'Texte', 'UI:DashletPlainText:Description' => 'Text pur (pas de mise en forme)', 'UI:DashletPlainText:Prop-Text' => 'Texte', diff --git a/js/dashboard.js b/js/dashboard.js index c84d12542..4f6db0371 100644 --- a/js/dashboard.js +++ b/js/dashboard.js @@ -171,7 +171,7 @@ $(function() add_dashlet_finalize: function(options, sDashletId, sDashletClass) { $('#dashlet_'+sDashletId) - .dashlet({dashlet_id: sDashletId, dashlet_class: sDashletClass}) + .dashlet({dashlet_id: sDashletId, dashlet_class: sDashletClass, dashlet_type: options.dashlet_type}) .dashlet('deselect_all') .dashlet('select') .draggable({ @@ -318,6 +318,7 @@ $(function() var sDashletClass = options.dashlet_class; oParams.dashlet_class = sDashletClass; oParams.dashlet_id = sDashletId; + oParams.dashlet_type = options.dashlet_type; var me = this; $.post(this.options.render_to, oParams, function(data){ me.ajax_div.html(data);