diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 57525d1bc..4149be0f0 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -438,10 +438,11 @@ EOF continue; } + $bCanEdit = UserRights::IsAdministrator() || $oAttDef->IsUserEditable(); $sDivId = $oDashboard->GetId(); $oPage->add('
'); $aExtraParams = array('query_params' => $this->ToArgsForQuery()); - $oDashboard->Render($oPage, false, $aExtraParams); + $oDashboard->Render($oPage, false, $aExtraParams, $bCanEdit); $oPage->add('
'); } } diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 6d6278422..d0a98e667 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -451,8 +451,9 @@ EOF * @param \iTopWebPage $oPage * @param bool $bEditMode * @param array $aExtraParams + * @param bool $bCanEdit */ - public function Render($oPage, $bEditMode = false, $aExtraParams = array()) + public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true) { $oPage->add('
'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'
'); @@ -582,6 +583,7 @@ class RuntimeDashboard extends Dashboard { protected $bCustomized; private $sDefinitionFile = ''; + private $sReloadURL = null; public function __construct($sId) @@ -599,6 +601,8 @@ class RuntimeDashboard extends Dashboard /** * @param \DesignerForm $oForm * + * @param array $aExtraParams + * * @throws \Exception */ protected function SetFormParams($oForm, $aExtraParams = array()) @@ -708,7 +712,7 @@ class RuntimeDashboard extends Dashboard * * @throws \Exception */ - public function Render($oPage, $bEditMode = false, $aExtraParams = array()) + public function Render($oPage, $bEditMode = false, $aExtraParams = array(), $bCanEdit = true) { if (!isset($aExtraParams['query_params']) && isset($aExtraParams['this->class'])) { @@ -754,7 +758,7 @@ class RuntimeDashboard extends Dashboard function ReloadDashboard$sDivId() { // Do not reload when a dialog box is active - if (!($('.ui-dialog:visible').length > 0)) + if (!($('.ui-dialog:visible').length > 0) && $('.dashboard_contents#$sDivId').is(':visible')) { $('.dashboard_contents#$sDivId').block(); $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', @@ -782,9 +786,11 @@ EOF ); } - $this->RenderDashboardSelector($oPage); - - $this->RenderEditionTools($oPage, $aAjaxParams); + if ($bCanEdit) + { + $this->RenderDashboardSelector($oPage); + $this->RenderEditionTools($oPage, $aAjaxParams); + } } } @@ -852,7 +858,7 @@ EOF utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions); $sEditMenu .= $oPage->RenderPopupMenuItems($aActions); $sEditMenu = addslashes($sEditMenu); - + $sReloadURL = $this->GetReloadURL(); $oPage->add_ready_script( <<iAutoReloadSec; $sTitle = addslashes($this->sTitle); $sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php'; + $sReloadURL = $this->GetReloadURL(); $sExitConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage')); $sCancelConfirmationMessage = addslashes(Dict::S('UI:CancelConfirmationMessage')); @@ -1019,8 +1026,8 @@ $('#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', extra_params: $sJSExtraParams}, - render_to: '$sUrl', render_parameters: {operation: 'render_dashboard', extra_params: $sJSExtraParams}, + submit_to: '$sUrl', submit_parameters: {operation: 'save_dashboard', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'}, + render_to: '$sUrl', render_parameters: {operation: 'render_dashboard', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'}, new_dashlet_parameters: {operation: 'new_dashlet'} }); @@ -1237,4 +1244,14 @@ EOF { $this->sDefinitionFile = $sDefinitionFile; } + + public function GetReloadURL() + { + return $this->sReloadURL; + } + + public function SetReloadURL($sReloadURL) + { + $this->sReloadURL = $sReloadURL; + } } \ No newline at end of file diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index ff670f5b2..3f09eb194 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -928,7 +928,7 @@ class DisplayBlock $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie'; $sTitle = isset($aExtraParams['chart_title']) ? '

'.htmlentities(Dict::S($aExtraParams['chart_title']), ENT_QUOTES, 'UTF-8').'

' : ''; - $sHtml = "$sTitle
\n"; + $sHtml = "$sTitle
\n"; $sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : ''; $sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '¶ms[group_by_expr]='.$aExtraParams['group_by_expr'] : ''; $sFilter = $this->m_oFilter->serialize(); @@ -1004,6 +1004,7 @@ EOF $sJson = json_encode($aValues); $oPage->add_ready_script( <<') . '

'; $sHtml .= "
"; $sHtml .= ''; - $sHtml .= ' '; - $sHtml .= ''; + $sHtml .= ' '; + $sHtml .= ''; + $sHtml .= ' '; + + $aResolutionChoices = array('100%' => Dict::S('UI:PrintResolution:FullSize'), + '19cm' => Dict::S('UI:PrintResolution:A4Portrait'), + '27.7cm' => Dict::S('UI:PrintResolution:A4Landscape'), + '19.6cm' => Dict::S('UI:PrintResolution:LetterPortrait'), + '25.9cm' => Dict::S('UI:PrintResolution:LetterLandscape'), + ); + $sHtml .= +<< +EOF + ; + $bIsSelected = true; + foreach ($aResolutionChoices as $sValue => $sText) + { + $sHtml .= ''; + $bIsSelected = false; + } + $sHtml .= ""; + $sHtml .= ""; + $sHtml .= "
"; } // Render the revision number @@ -979,7 +1001,9 @@ EOF $sHtml .= ' '; $sHtml .= self::FilterXSS($this->s_content); $sHtml .= ' '; - } elseif ($this->GetOutputFormat() == 'html') { + } + elseif ($this->GetOutputFormat() == 'html') + { $oAppContext = new ApplicationContext(); $sUserName = UserRights::GetUser(); @@ -1171,6 +1195,10 @@ EOF; $sHtml .= self::FilterXSS($this->s_content); } + if ($this->IsPrintableVersion()) { + $sHtml .= '
'; + } + $sHtml .= "\n"; $sHtml .= "\n"; diff --git a/application/menunode.class.inc.php b/application/menunode.class.inc.php index 17657ab6d..4ae819185 100644 --- a/application/menunode.class.inc.php +++ b/application/menunode.class.inc.php @@ -1166,6 +1166,7 @@ class DashboardMenuNode extends MenuNode { $sDivId = preg_replace('/[^a-zA-Z0-9_]/', '', $this->sMenuId); $oPage->add('
'); + $oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams)); $oDashboard->Render($oPage, false, $aExtraParams); $oPage->add('
'); diff --git a/application/utils.inc.php b/application/utils.inc.php index 7d5dfc4b8..939224137 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -1114,6 +1114,12 @@ class utils 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' })"), ); + if ($oDashboard->GetReloadURL()) + { + $aResult[] = new SeparatorPopupMenuItem(); + $aResult[] = new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $oDashboard->GetReloadURL().'&printable=1', '_blank'); + } + break; default: diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 113680a03..d83fb4eac 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -1254,7 +1254,7 @@ class AttributeDashboard extends AttributeDefinition static public function ListExpectedParams() { return array_merge(parent::ListExpectedParams(), - array("definition_file")); + array("definition_file", "is_user_editable")); } public function GetDashboard() @@ -1265,6 +1265,11 @@ class AttributeDashboard extends AttributeDefinition return RuntimeDashboard::GetDashboard($sFilePath, $sClass.'__'.$sAttCode); } + public function IsUserEditable() + { + return $this->Get('is_user_editable'); + } + public function IsWritable() { return false; diff --git a/css/print.css b/css/print.css index 0d73a1ddf..75d599666 100644 --- a/css/print.css +++ b/css/print.css @@ -16,12 +16,20 @@ div.graph_config { display:none; } h2.printable-tab-title { page-break-after: avoid; } +h1 { + page-break-after: avoid; +} div#tabbedContent_0 { border:none; } p a, .ui-widget-content td a, p a:hover, .ui-widget-content td a:hover, p a:visited, .ui-widget-content td a:visited, td a, td a:visited, td a:hover { padding-left: 0; background: transparent; } -body { margin:0; } +body { + margin:10px; +} +@page { + margin: 1cm; +} .printable-tab { -webkit-region-break-inside: avoid; diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php index 20cc7ac69..dc307b69b 100644 --- a/dictionaries/en.dictionary.itop.ui.php +++ b/dictionaries/en.dictionary.itop.ui.php @@ -1132,6 +1132,13 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:Button:Refresh' => 'Refresh', 'UI:Button:GoPrint' => 'Print...', 'UI:ExplainPrintable' => 'Click onto the %1$s icon to hide items from the print.
Use the "print preview" feature of your browser to preview before printing.
Note: this header and the other tuning controls will not be printed.', + 'UI:PrintResolution:FullSize' => 'Full size', + 'UI:PrintResolution:A4Portrait' => 'A4 Portrait', + 'UI:PrintResolution:A4Landscape' => 'A4 Landscape', + 'UI:PrintResolution:LetterPortrait' => 'Letter Portrait', + 'UI:PrintResolution:LetterLandscape' => 'Letter Landscape', + 'UI:Toggle:StandardDashboard' => 'Standard', + 'UI:Toggle:CustomDashboard' => 'Custom', 'UI:ConfigureThisList' => 'Configure This List...', 'UI:ListConfigurationTitle' => 'List Configuration', diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 078dbf34d..25b4379bb 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -955,10 +955,15 @@ try $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); $aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data'); $sDashboardFile = utils::ReadParam('file', '', false, 'raw_data'); + $sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data'); $oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId); $aResult = array('error' => ''); if (!is_null($oDashboard)) { + if (!empty($sReloadURL)) + { + $oDashboard->SetReloadURL($sReloadURL); + } $oDashboard->Render($oPage, false, $aExtraParams); } $oPage->add_ready_script("$('.dashboard_contents table.listResults').tableHover(); $('.dashboard_contents table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); @@ -967,6 +972,7 @@ try case 'save_dashboard': $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); $aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data'); + $sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data'); $sJSExtraParams = json_encode($aExtraParams); $aParams = array(); $aParams['layout_class'] = utils::ReadParam('layout_class', ''); @@ -984,7 +990,7 @@ try <<FromParams($aParams); + $oDashboard->SetReloadURL($sReloadURL); $oDashboard->Render($oPage, true /* bEditMode */, $aExtraParams); break; @@ -1033,9 +1041,14 @@ EOF $sId = utils::ReadParam('id', '', false, 'raw_data'); $aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data'); $sDashboardFile = utils::ReadParam('file', '', false, 'raw_data'); + $sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data'); $oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sId); if (!is_null($oDashboard)) { + if (!empty($sReloadURL)) + { + $oDashboard->SetReloadURL($sReloadURL); + } $oDashboard->RenderEditor($oPage, $aExtraParams); } break; diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php index 69e5c03b3..c1dca7e0a 100644 --- a/setup/compiler.class.inc.php +++ b/setup/compiler.class.inc.php @@ -1436,6 +1436,7 @@ EOF elseif ($sAttType == 'AttributeDashboard') { $aTagFieldsInfo[] = $sAttCode; + $aParameters['is_user_editable'] = $this->GetPropBoolean($oField, 'is_user_editable', true); $aParameters['definition_file'] = $this->GetPropString($oField, 'definition_file'); if ($aParameters['definition_file'] == null)