mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-21 17:48:43 +02:00
N°1408 - AttributeDashboard first implementation
This commit is contained in:
@@ -398,6 +398,54 @@ EOF
|
||||
$this->aFieldsMap[$sAttCode] = $sInputId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param $bEditMode
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function DisplayDashboards($oPage, $bEditMode)
|
||||
{
|
||||
if ($bEditMode || $this->IsNew())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$aList = $this->FlattenZList(MetaModel::GetZListItems(get_class($this), 'details'));
|
||||
if (count($aList) == 0)
|
||||
{
|
||||
// Empty ZList defined, display all the dashboard attributes defined
|
||||
$aList = array_keys(MetaModel::ListAttributeDefs(get_class($this)));
|
||||
}
|
||||
$sClass = get_class($this);
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
// Display mode
|
||||
if (!$oAttDef instanceof AttributeDashboard)
|
||||
{
|
||||
continue;
|
||||
} // Process only dashboards attributes...
|
||||
|
||||
$oPage->SetCurrentTab($oAttDef->GetLabel());
|
||||
|
||||
// Load the dashboard
|
||||
$oDashboard = $oAttDef->GetDashboard();
|
||||
if (is_null($oDashboard))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$sDivId = $oDashboard->GetId();
|
||||
$oPage->add('<div class="dashboard_contents" id="'.$sDivId.'">');
|
||||
$oDashboard->Render($oPage, false, array());
|
||||
$oPage->add('</div>');
|
||||
$oDashboard->RenderEditionTools($oPage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
@@ -857,6 +905,18 @@ EOF
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \iTopWebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function DisplayDetails(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
$sTemplate = Utils::ReadFromFile(MetaModel::GetDisplayTemplate(get_class($this)));
|
||||
@@ -884,6 +944,7 @@ EOF
|
||||
$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
|
||||
$this->DisplayBareProperties($oPage, $bEditMode);
|
||||
$this->DisplayBareRelations($oPage, $bEditMode);
|
||||
$this->DisplayDashboards($oPage, $bEditMode);
|
||||
//$oPage->SetCurrentTab(Dict::S('UI:HistoryTab'));
|
||||
//$this->DisplayBareHistory($oPage, $bEditMode);
|
||||
$oPage->AddAjaxTab(Dict::S('UI:HistoryTab'),
|
||||
@@ -2849,6 +2910,10 @@ EOF
|
||||
$sDisplayValue .= "<br/>".Dict::Format('UI:DownloadDocument_',
|
||||
$oDocument->GetDownloadLink(get_class($this), $this->GetKey(), $sAttCode)).", \n";
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeDashboard)
|
||||
{
|
||||
$sDisplayValue = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDisplayValue = $this->GetAsHTML($sAttCode);
|
||||
|
||||
@@ -50,6 +50,11 @@ abstract class Dashboard
|
||||
$this->sId = $sId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sXml
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function FromXml($sXml)
|
||||
{
|
||||
$this->aCells = array(); // reset the content of the dashboard
|
||||
@@ -509,6 +514,7 @@ EOF
|
||||
* Return an array of dashlets available for selection.
|
||||
*
|
||||
* @return array
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function GetAvailableDashlets()
|
||||
{
|
||||
@@ -561,11 +567,21 @@ EOF
|
||||
}
|
||||
return 'DashletUnknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetId()
|
||||
{
|
||||
return $this->sId;
|
||||
}
|
||||
}
|
||||
|
||||
class RuntimeDashboard extends Dashboard
|
||||
{
|
||||
protected $bCustomized;
|
||||
private $sDefinitionFile = '';
|
||||
|
||||
|
||||
public function __construct($sId)
|
||||
{
|
||||
@@ -630,7 +646,53 @@ class RuntimeDashboard extends Dashboard
|
||||
utils::PopArchiveMode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $sDashboardFile file name relative to the current module folder
|
||||
* @param string $sDashBoardCode code of the dashboard either menu_id or <class>__<attcode>
|
||||
*
|
||||
* @return null|RuntimeDashboard
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public static function GetDashboard($sDashboardFile, $sDashBoardCode)
|
||||
{
|
||||
$bCustomized = false;
|
||||
|
||||
// Search for an eventual user defined dashboard
|
||||
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oUDSearch->AddCondition('menu_code', $sDashBoardCode, '=');
|
||||
$oUDSet = new DBObjectSet($oUDSearch);
|
||||
if ($oUDSet->Count() > 0)
|
||||
{
|
||||
// Assuming there is at most one couple {user, menu}!
|
||||
$oUserDashboard = $oUDSet->Fetch();
|
||||
$sDashboardDefinition = $oUserDashboard->Get('contents');
|
||||
$bCustomized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDashboardDefinition = @file_get_contents($sDashboardFile);
|
||||
}
|
||||
|
||||
if ($sDashboardDefinition !== false)
|
||||
{
|
||||
$oDashboard = new RuntimeDashboard($sDashBoardCode);
|
||||
$oDashboard->FromXml($sDashboardDefinition);
|
||||
$oDashboard->SetCustomFlag($bCustomized);
|
||||
$oDashboard->SetDefinitionFile($sDashboardFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDashboard = null;
|
||||
}
|
||||
return $oDashboard;
|
||||
}
|
||||
|
||||
public function RenderEditionTools(WebPage $oPage)
|
||||
{
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||
@@ -638,7 +700,8 @@ class RuntimeDashboard extends Dashboard
|
||||
$sEditMenu = "<div id=\"DashboardMenu\"><ul><li><img src=\"../images/pencil-menu.png\"><ul>";
|
||||
|
||||
$aActions = array();
|
||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}')");
|
||||
$sFile = addslashes($this->sDefinitionFile);
|
||||
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:Edit'), "return EditDashboard('{$this->sId}', '$sFile')");
|
||||
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
|
||||
|
||||
if ($this->bCustomized)
|
||||
@@ -662,9 +725,9 @@ EOF
|
||||
);
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
function EditDashboard(sId)
|
||||
function EditDashboard(sId, sDashboardFile)
|
||||
{
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId},
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'dashboard_editor', id: sId, file: sDashboardFile},
|
||||
function(data)
|
||||
{
|
||||
$('body').append(data);
|
||||
@@ -1007,4 +1070,20 @@ $('#dashlet_creation_dlg').dialog({
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDefinitionFile()
|
||||
{
|
||||
return $this->sDefinitionFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDefinitionFile
|
||||
*/
|
||||
public function SetDefinitionFile($sDefinitionFile)
|
||||
{
|
||||
$this->sDefinitionFile = $sDefinitionFile;
|
||||
}
|
||||
}
|
||||
@@ -1149,33 +1149,7 @@ class DashboardMenuNode extends MenuNode
|
||||
*/
|
||||
public function GetDashboard()
|
||||
{
|
||||
$sDashboardDefinition = @file_get_contents($this->sDashboardFile);
|
||||
if ($sDashboardDefinition !== false)
|
||||
{
|
||||
$bCustomized = false;
|
||||
|
||||
// Search for an eventual user defined dashboard, overloading the existing one
|
||||
$oUDSearch = new DBObjectSearch('UserDashboard');
|
||||
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oUDSearch->AddCondition('menu_code', $this->sMenuId, '=');
|
||||
$oUDSet = new DBObjectSet($oUDSearch);
|
||||
if ($oUDSet->Count() > 0)
|
||||
{
|
||||
// Assuming there is at most one couple {user, menu}!
|
||||
$oUserDashboard = $oUDSet->Fetch();
|
||||
$sDashboardDefinition = $oUserDashboard->Get('contents');
|
||||
$bCustomized = true;
|
||||
|
||||
}
|
||||
$oDashboard = new RuntimeDashboard($this->sMenuId);
|
||||
$oDashboard->FromXml($sDashboardDefinition);
|
||||
$oDashboard->SetCustomFlag($bCustomized);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDashboard = null;
|
||||
}
|
||||
return $oDashboard;
|
||||
return RuntimeDashboard::GetDashboard($this->sDashboardFile, $this->sMenuId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1199,6 +1173,7 @@ class DashboardMenuNode extends MenuNode
|
||||
if ($oDashboard->GetAutoReload())
|
||||
{
|
||||
$sId = $this->sMenuId;
|
||||
$sFile = addslashes($oDashboard->GetDefinitionFile());
|
||||
$sExtraParams = json_encode($aExtraParams);
|
||||
$iReloadInterval = 1000 * $oDashboard->GetAutoReloadInterval();
|
||||
$oPage->add_script(
|
||||
@@ -1213,7 +1188,7 @@ class DashboardMenuNode extends MenuNode
|
||||
{
|
||||
$('.dashboard_contents#'+sDivId).block();
|
||||
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
|
||||
{ operation: 'reload_dashboard', dashboard_id: '$sId', extra_params: oExtraParams},
|
||||
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: oExtraParams},
|
||||
function(data){
|
||||
$('.dashboard_contents#'+sDivId).html(data);
|
||||
$('.dashboard_contents#'+sDivId).unblock();
|
||||
|
||||
@@ -1104,19 +1104,22 @@ class utils
|
||||
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' })"),
|
||||
);
|
||||
break;
|
||||
// $param is a Dashboard
|
||||
/** @var \RuntimeDashboard $oDashboard */
|
||||
$oDashboard = $param;
|
||||
$sDashboardId = $oDashboard->GetId();
|
||||
$sDashboardFile = $oDashboard->GetDefinitionFile();
|
||||
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
|
||||
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
|
||||
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
|
||||
$sDashboardFileJS = addslashes($sDashboardFile);
|
||||
$sDashboardFileURL = urlencode($sDashboardFile);
|
||||
$aResult = array(
|
||||
new SeparatorPopupMenuItem(),
|
||||
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
|
||||
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn' })"),
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown type of menu, do nothing
|
||||
|
||||
@@ -1249,6 +1249,53 @@ abstract class AttributeDefinition
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeDashboard extends AttributeDefinition
|
||||
{
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(),
|
||||
array("definition_file"));
|
||||
}
|
||||
|
||||
public function GetDashboard()
|
||||
{
|
||||
$sAttCode = $this->GetCode();
|
||||
$sClass = MetaModel::GetAttributeOrigin($this->GetHostClass(), $sAttCode);
|
||||
$sFilePath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/'.$this->Get('definition_file');
|
||||
return RuntimeDashboard::GetDashboard($sFilePath, $sClass.'__'.$sAttCode);
|
||||
}
|
||||
|
||||
public function IsWritable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetEditClass()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function GetBasicFilterOperators()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function GetBasicFilterLooseOperator()
|
||||
{
|
||||
return '=';
|
||||
}
|
||||
|
||||
public function GetBasicFilterSQLExpr($sOpCode, $value)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of objects directly linked to an object, and being part of its definition
|
||||
*
|
||||
|
||||
@@ -2251,6 +2251,7 @@ a.summary, a.summary:hover {
|
||||
}
|
||||
.dashboard_contents {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
#DashboardMenu {
|
||||
display: block;
|
||||
|
||||
@@ -2603,6 +2603,7 @@ a.summary, a.summary:hover {
|
||||
|
||||
.dashboard_contents {
|
||||
width: 100%;
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
#DashboardMenu {
|
||||
|
||||
@@ -412,6 +412,57 @@
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="dashboard" xsi:type="AttributeDashboard">
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title>Test Modified</title>
|
||||
<auto_reload>
|
||||
<enabled>false</enabled>
|
||||
<interval>300</interval>
|
||||
</auto_reload>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="9" xsi:type="DashletHeaderDynamic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:RequestManagement</title>
|
||||
<icon>itop-welcome-itil/images/user-request-deadline.png</icon>
|
||||
<subtitle>Menu:UserRequest:OpenRequests</subtitle>
|
||||
<query>SELECT UserRequest WHERE status != "closed"</query>
|
||||
<group_by>status</group_by>
|
||||
<values>assigned,escalated_tto,escalated_ttr,new,resolved</values>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="1">
|
||||
<rank>1</rank>
|
||||
<dashlets>
|
||||
<dashlet id="10" xsi:type="DashletGroupByBars">
|
||||
<rank>0</rank>
|
||||
<title>Callers</title>
|
||||
<query>SELECT UserRequest</query>
|
||||
<group_by>caller_id</group_by>
|
||||
<style>bars</style>
|
||||
<aggregation_function>count</aggregation_function>
|
||||
<aggregation_attribute></aggregation_attribute>
|
||||
<limit></limit>
|
||||
<order_by>function</order_by>
|
||||
<order_direction>desc</order_direction>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="2">
|
||||
<rank>2</rank>
|
||||
<dashlets>
|
||||
<dashlet id="0" xsi:type="DashletEmptyCell">
|
||||
<rank>0</rank>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</field>
|
||||
</fields>
|
||||
<lifecycle>
|
||||
<highlight_scale>
|
||||
@@ -1458,6 +1509,9 @@
|
||||
<item id="workorders_list">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="dashboard">
|
||||
<rank>45</rank>
|
||||
</item>
|
||||
<item id="col:col1">
|
||||
<rank>50</rank>
|
||||
<items>
|
||||
|
||||
@@ -441,8 +441,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Error:ObjectAlreadyCloned' => 'Error: the object has already been cloned!',
|
||||
'UI:Error:ObjectAlreadyCreated' => 'Error: the object has already been created!',
|
||||
'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Error: invalid stimulus "%1$s" on object %2$s in state "%3$s".',
|
||||
|
||||
|
||||
'UI:Error:InvalidDashboardFile' => 'Error: invalid dashboard file',
|
||||
|
||||
'UI:GroupBy:Count' => 'Count',
|
||||
'UI:GroupBy:Count+' => 'Number of elements',
|
||||
'UI:CountOfObjects' => '%1$d objects matching the criteria.',
|
||||
|
||||
@@ -308,6 +308,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI:Error:ObjectAlreadyCloned' => 'Erreur: l\'objet a déjà été dupliqué !',
|
||||
'UI:Error:ObjectAlreadyCreated' => 'Erreur: l\'objet a déjà été créé !',
|
||||
'UI:Error:Invalid_Stimulus_On_Object_In_State' => 'Erreur: le stimulus "%1$s" n\'est pas valide pour l\'objet %2$s dans l\'état "%3$s".',
|
||||
'UI:Error:InvalidDashboardFile' => 'Erreur: Le fichier tableau de bord est invalide',
|
||||
'UI:GroupBy:Count' => 'Nombre',
|
||||
'UI:GroupBy:Count+' => 'Nombre d\'éléments',
|
||||
'UI:CountOfObjects' => '%1$d objets correspondants aux critères.',
|
||||
|
||||
@@ -910,25 +910,68 @@ try
|
||||
}
|
||||
break;
|
||||
|
||||
case 'export_dashboard':
|
||||
$sDashboardId = utils::ReadParam('id', '', false, 'raw_data');
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId);
|
||||
if (!is_null($oDashboard))
|
||||
{
|
||||
$oPage->TrashUnexpectedOutput();
|
||||
$oPage->SetContentType('text/xml');
|
||||
$oPage->SetContentDisposition('attachment', 'dashboard_'.$oDashboard->GetTitle().'.xml');
|
||||
$oPage->add($oDashboard->ToXml());
|
||||
}
|
||||
break;
|
||||
|
||||
case 'import_dashboard':
|
||||
$sDashboardId = utils::ReadParam('id', '', false, 'raw_data');
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId);
|
||||
$aResult = array('error' => '');
|
||||
if (!is_null($oDashboard))
|
||||
{
|
||||
try
|
||||
{
|
||||
$oDoc = utils::ReadPostedDocument('dashboard_upload_file');
|
||||
$oDashboard->FromXml($oDoc->GetData());
|
||||
$oDashboard->Save();
|
||||
} catch (DOMException $e)
|
||||
{
|
||||
$aResult = array('error' => Dict::S('UI:Error:InvalidDashboardFile'));
|
||||
} catch (Exception $e)
|
||||
{
|
||||
$aResult = array('error' => $e->getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult['error'] = 'Dashboard id="'.$sMenuId.'" not found.';
|
||||
}
|
||||
$oPage->add(json_encode($aResult));
|
||||
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);
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId);
|
||||
$aResult = array('error' => '');
|
||||
if (!is_null($oDashboard))
|
||||
{
|
||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||
}
|
||||
$oPage->add_ready_script("$('.dashboard_contents table.listResults').tableHover(); $('.dashboard_contents table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );");
|
||||
break;
|
||||
|
||||
case 'dashboard_editor':
|
||||
$sId = utils::ReadParam('id', '', false, 'raw_data');
|
||||
ApplicationMenu::LoadAdditionalMenus();
|
||||
$idx = ApplicationMenu::GetMenuIndexById($sId);
|
||||
/** @var \DashboardMenuNode $oMenu */
|
||||
$oMenu = ApplicationMenu::GetMenuNode($idx);
|
||||
$oMenu->RenderEditor($oPage);
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sId);
|
||||
if (!is_null($oDashboard))
|
||||
{
|
||||
$oDashboard->RenderEditor($oPage);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'new_dashlet':
|
||||
@@ -1024,15 +1067,7 @@ try
|
||||
$oDashboard->FromParams($aParams);
|
||||
$oDashboard->Save();
|
||||
// trigger a reload of the current page since the dashboard just changed
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
var sLocation = new String(window.location.href);
|
||||
var sNewLocation = sLocation.replace('&edit=1', '');
|
||||
sNewLocation = sLocation.replace(/#(.?)$/, ''); // Strips everything after the hash, since IF the URL does not change AND contains a hash, then Chrome does not reload the page
|
||||
window.location.href = sNewLocation;
|
||||
EOF
|
||||
);
|
||||
$oPage->add_ready_script("sLocation = new String(window.location.href); window.location.href=sLocation.replace('&edit=1', '');"); // reloads the page, doing a GET even if we arrived via a POST
|
||||
$oPage->add_ready_script("location.reload(true);");
|
||||
break;
|
||||
|
||||
case 'revert_dashboard':
|
||||
@@ -1041,7 +1076,7 @@ EOF
|
||||
$oDashboard->Revert();
|
||||
|
||||
// trigger a reload of the current page since the dashboard just changed
|
||||
$oPage->add_ready_script("window.location.href=window.location.href;"); // reloads the page, doing a GET even if we arrived via a POST
|
||||
$oPage->add_ready_script("location.reload(true);");
|
||||
break;
|
||||
|
||||
case 'render_dashboard':
|
||||
@@ -1165,51 +1200,6 @@ EOF
|
||||
}
|
||||
break;
|
||||
|
||||
case 'export_dashboard':
|
||||
$sMenuId = utils::ReadParam('id', '', false, 'raw_data');
|
||||
ApplicationMenu::LoadAdditionalMenus();
|
||||
$index = ApplicationMenu::GetMenuIndexById($sMenuId);
|
||||
$oMenu = ApplicationMenu::GetMenuNode($index);
|
||||
if ($oMenu instanceof DashboardMenuNode)
|
||||
{
|
||||
$oDashboard = $oMenu->GetDashboard();
|
||||
|
||||
$oPage->TrashUnexpectedOutput();
|
||||
$oPage->SetContentType('text/xml');
|
||||
$oPage->SetContentDisposition('attachment', $oMenu->GetLabel().'.xml');
|
||||
$oPage->add($oDashboard->ToXml());
|
||||
}
|
||||
break;
|
||||
|
||||
case 'import_dashboard':
|
||||
$sMenuId = utils::ReadParam('id', '', false, 'raw_data');
|
||||
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;
|
||||
|
||||
case 'about_box':
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
|
||||
@@ -1433,6 +1433,37 @@ EOF
|
||||
$aParameters['depends_on'] = $sDependencies;
|
||||
$aParameters['class_field'] = $this->GetMandatoryPropString($oField, 'class_field');
|
||||
}
|
||||
elseif ($sAttType == 'AttributeDashboard')
|
||||
{
|
||||
$aTagFieldsInfo[] = $sAttCode;
|
||||
$aParameters['definition_file'] = $this->GetPropString($oField, 'definition_file');
|
||||
|
||||
if ($aParameters['definition_file'] == null)
|
||||
{
|
||||
$oDashboardDefinition = $oField->GetOptionalElement('definition');
|
||||
if ($oDashboardDefinition == null)
|
||||
{
|
||||
throw(new DOMFormatException('Missing definition for Dashboard Attribute "'.$sAttCode.'" expecting either a tag "definition_file" or "definition".'));
|
||||
}
|
||||
$sFileName = strtolower($sClass).'__'.strtolower($sAttCode).'_dashboard.xml';
|
||||
|
||||
$oXMLDoc = new DOMDocument('1.0', 'UTF-8');
|
||||
$oXMLDoc->formatOutput = true; // indent (must be loaded with option LIBXML_NOBLANKS)
|
||||
$oXMLDoc->preserveWhiteSpace = true; // otherwise the formatOutput option would have no effect
|
||||
|
||||
$oRootNode = $oXMLDoc->createElement('dashboard'); // make sure that the document is not empty
|
||||
$oRootNode->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance");
|
||||
$oXMLDoc->appendChild($oRootNode);
|
||||
foreach($oDashboardDefinition->childNodes as $oNode)
|
||||
{
|
||||
$oDefNode = $oXMLDoc->importNode($oNode, true); // layout, cells, etc Nodes and below
|
||||
$oRootNode->appendChild($oDefNode);
|
||||
}
|
||||
$sFileName = $sModuleRelativeDir.'/'.$sFileName;
|
||||
$oXMLDoc->save($sTempTargetDir.'/'.$sFileName);
|
||||
$aParameters['definition_file'] = "'".str_replace("'", "\\'", $sFileName)."'";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aParameters['allowed_values'] = 'null'; // or "new ValueSetEnum('SELECT xxxx')"
|
||||
@@ -1970,7 +2001,7 @@ EOF;
|
||||
{
|
||||
throw(new DOMFormatException('Missing definition for Dashboard menu "'.$sMenuId.'" expecting either a tag "definition_file" or "definition".'));
|
||||
}
|
||||
$sFileName = strtolower(str_replace(array(':', '/', '\\', '*'), '_', $sMenuId)).'_dashboard_menu.xml';
|
||||
$sFileName = strtolower(str_replace(array(':', '/', '\\', '*'), '_', $sMenuId)).'_dashboard.xml';
|
||||
$sTemplateSpec = $this->PathToPHP($sFileName, $sModuleRelativeDir);
|
||||
|
||||
$oXMLDoc = new DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
Reference in New Issue
Block a user