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);