N°2735 Fix cannot edit new dashlet properties regression

Was introduced by cf83bc73
This commit is contained in:
Pierre Goiffon
2020-02-24 16:15:00 +01:00
parent 368b49ef8f
commit dfc894f6fd
4 changed files with 102 additions and 51 deletions

View File

@@ -1127,7 +1127,7 @@ EOF
$sAutoApplyConfirmationMessage = addslashes(Dict::S('UI:AutoApplyConfirmationMessage'));
$oPage->add_ready_script(
<<<EOF
<<<JS
window.bLeavingOnUserAction = false;
$('#dashboard_editor').dialog({
@@ -1170,11 +1170,17 @@ $('#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', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl', render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
new_dashlet_parameters: {operation: 'new_dashlet'}
dashboard_id: '$sId',
layout_class: '$sLayoutClass',
title: '$sTitle',
auto_reload: $sAutoReload,
auto_reload_sec: $sAutoReloadSec,
submit_to: '$sUrl',
submit_parameters: {operation: 'save_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
render_to: '$sUrl',
render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
new_dashlet_parameters: {operation: 'new_dashlet'},
new_dashletid_parameters: {operation: 'new_dashlet_id'}
});
dashboard_prop_size = GetUserPreference('dashboard_prop_size', 350);
@@ -1212,7 +1218,7 @@ window.onbeforeunload = function() {
}
// return nothing ! safer for IE
};
EOF
JS
);
$oPage->add_ready_script("");
}
@@ -1352,7 +1358,7 @@ EOF
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$oPage->add_ready_script(
<<<EOF
<<<JS
$('#dashlet_creation_dlg').dialog({
width: 600,
modal: true,
@@ -1381,7 +1387,7 @@ $('#dashlet_creation_dlg').dialog({
],
close: function() { $(this).remove(); }
});
EOF
JS
);
}

View File

@@ -46,7 +46,38 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
{
$this->iNbCols = 1;
}
/**
* N°2634 : we must have a unique id per dashlet !
* To avoid collision with other dashlets with the same ID we prefix it with row/cell id
* Collisions typically happen with extensions.
*
* @param boolean $bIsCustomized
* @param string $sDashboardDivId
* @param int $iRow
* @param int $iCell
* @param string $sDashletIdOrig
*
* @return string
*
* @since 2.7.0 N°2735
*/
public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCell, $sDashletIdOrig)
{
if(strpos($sDashletIdOrig, 'IDrow') !== false)
{
return $sDashletIdOrig;
}
$sDashletId = $sDashboardDivId."_IDrow$iRow-col$iCell-$sDashletIdOrig";
if ($bIsCustomized)
{
$sDashletId = 'CUSTOM_'.$sDashletId;
}
return $sDashletId;
}
protected function TrimCell($aDashlets)
{
$aKeys = array_reverse(array_keys($aDashlets));
@@ -115,7 +146,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
for($iRows = 0; $iRows < $iNbRows; $iRows++)
{
$oPage->add('<tr>');
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
{
$sCellClass = ($iRows == $iNbRows-1) ? $sClass.' layout_last_used_rank' : $sClass;
@@ -128,23 +159,13 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
/** @var \Dashlet $oDashlet */
foreach($aDashlets as $oDashlet)
{
if ($oDashlet->IsVisible())
if ($oDashlet::IsVisible())
{
$sDashletIdOrig = $oDashlet->GetID();
$sDashletId = $sDashletIdOrig;
if(strpos($sDashletId, 'IDrow') === false)
{
$sDashboardDivId = $aExtraParams['dashboard_div_id'];
// N°2634 : we must have a unique id per dashlet !
// To avoid collision with other dashlets with the same ID we prefix it with row/cell id
// Collisions typically happen with extensions.
$sDashletId = $sDashboardDivId."_IDrow$iRows-col$iCols-$sDashletId";
if (array_key_exists('bCustomized', $aExtraParams) && ((bool)$aExtraParams['bCustomized']) === true)
{
$sDashletId = 'CUSTOM_'.$sDashletId;
}
$oDashlet->SetID($sDashletId);
}
$sDashboardDivId = $aExtraParams['dashboard_div_id'];
$bIsCustomized = (array_key_exists('bCustomized', $aExtraParams) && ((bool)$aExtraParams['bCustomized']) === true);
$sDashletId = self::GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRows, $iCols, $sDashletIdOrig);
$oDashlet->SetID($sDashletId);
$this->UpdateDashletsUserPrefs($oDashlet, $sDashletIdOrig, $aExtraParams);
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
}
@@ -167,7 +188,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
if ($bEditMode) // Add one row for extensibility
{
$sStyle = 'style="border: 1px #ccc dashed; width:'.$fColSize.'%;" class="layout_cell edit_mode layout_extension" data-dashboard-cell-index="'.$iCellIdx.'"';
$oPage->add('<tr>');
$oPage->add("<tr data-dashboard-row-index=\"$iRows\">");
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
{
$oPage->add("<td $sStyle>");

View File

@@ -11,6 +11,7 @@ $(function()
$.widget( "itop.dashboard",
{
// default options
// real values must be provided when instanciating the widget : $node.dashboard(...)
options:
{
dashboard_id: '',
@@ -22,7 +23,8 @@ $(function()
submit_parameters: {},
render_to: 'index.php',
render_parameters: {},
new_dashlet_parameters: {}
new_dashlet_parameters: {},
new_dashletid_parameters: {}
},
// the constructor
@@ -31,10 +33,10 @@ $(function()
var me = this;
this.element
.addClass('itop-dashboard')
.bind('add_dashlet.itop_dashboard', function(event, oParams){
me.add_dashlet(oParams);
});
.addClass('itop-dashboard')
.bind('add_dashlet.itop_dashboard', function(event, oParams){
me.add_dashlet(oParams);
});
this.ajax_div = $('<div></div>');
this.element.after(this.ajax_div);
@@ -103,20 +105,6 @@ $(function()
return oState;
},
_get_new_id: function()
{
var iMaxId = 0;
this.element.find(':itop-dashlet').each(function() {
var oDashlet = $(this).data('itopDashlet');
if(oDashlet)
{
var oDashletParams = oDashlet.get_params();
var id = parseInt(oDashletParams.dashlet_id, 10);
if (id > iMaxId) iMaxId = id;
}
});
return 1 + iMaxId;
},
_make_draggable: function()
{
var me = this;
@@ -154,19 +142,26 @@ $(function()
});
},
add_dashlet: function(options)
{
var $container = options.container,
iNumberOfExistingDashletInCell = $container.children("div.dashlet").length,
sTempDashletId = iNumberOfExistingDashletInCell+1;
this.get_dashletid_ajax(options, sTempDashletId);
},
add_dashlet_prepare: function(options, sFinalDashletId)
{
// 1) Create empty divs for the dashlet and its properties
//
var sDashletId = this._get_new_id();
var oDashlet = $('<div class="dashlet" id="dashlet_'+sDashletId+'"/>');
var oDashlet = $('<div class="dashlet" id="dashlet_'+sFinalDashletId+'"/>');
oDashlet.appendTo(options.container);
var oDashletProperties = $('<div class="dashlet_properties" id="dashlet_properties_'+sDashletId+'"/>');
var oDashletProperties = $('<div class="dashlet_properties" id="dashlet_properties_'+sFinalDashletId+'"/>');
oDashletProperties.appendTo($('#dashlet_properties'));
// 2) Ajax call to fill the divs with default values
// => in return, it must call add_dashlet_finalize
//
this.add_dashlet_ajax(options, sDashletId);
this.add_dashlet_ajax(options, sFinalDashletId);
},
add_dashlet_finalize: function(options, sDashletId, sDashletClass)
{
@@ -209,6 +204,7 @@ $(function()
$.widget( "itop.runtimedashboard", $.itop.dashboard,
{
// default options
// real values must be provided when instanciating the widget : $node.runtimedashboard(...)
options:
{
dashboard_id: '',
@@ -220,7 +216,8 @@ $(function()
submit_parameters: {},
render_to: 'index.php',
render_parameters: {},
new_dashlet_parameters: {}
new_dashlet_parameters: {},
new_dashletid_parameters: {}
},
// the constructor
@@ -246,6 +243,7 @@ $(function()
this._superApply(arguments);
},
// _setOptions is called with a hash of all options that are changing
_setOptions: function()
{
@@ -317,6 +315,22 @@ $(function()
}
});
},
// We need a unique dashlet id, we will get it using an ajax query
get_dashletid_ajax: function(options, sTempDashletId)
{
var $container = options.container;
var oParams = this.options.new_dashletid_parameters;
oParams.dashboardid = options.dashboard_id;
oParams.iRow = $container.closest("tr").data("dashboard-row-index");
oParams.iCell = $container.data("dashboard-cell-index");
oParams.dashletid = sTempDashletId;
var me = this;
$.post(this.options.render_to, oParams, function(data) {
sFinalDashletId = data;
me.add_dashlet_prepare(options, sFinalDashletId);
});
},
add_dashlet_ajax: function(options, sDashletId)
{
var oParams = this.options.new_dashlet_parameters;

View File

@@ -1215,6 +1215,16 @@ EOF
$oKPI->ComputeAndReport('Data fetch and format');
break;
case 'new_dashlet_id':
$sDashboardDivId = utils::ReadParam("dashboardid");
$iRow = utils::ReadParam("iRow");
$iCell = utils::ReadParam("iCell");
$sDashletIdOrig = utils::ReadParam("dashletid");
$sFinalDashletId = DashboardLayoutMultiCol::GetDashletUniqueId(true, $sDashboardDivId, $iRow, $iCell, $sDashletIdOrig);
$oPage = new ajax_page('');
$oPage->add($sFinalDashletId);
break;
case 'new_dashlet':
require_once(APPROOT.'application/forms.class.inc.php');
require_once(APPROOT.'application/dashlet.class.inc.php');