Merge remote-tracking branch 'origin/support/3.2' into develop

This commit is contained in:
Molkobain
2024-03-06 14:47:29 +01:00
48 changed files with 744 additions and 246 deletions

View File

@@ -2429,7 +2429,7 @@ HTML;
$sInputType = self::ENUM_INPUT_TYPE_IMAGE; $sInputType = self::ENUM_INPUT_TYPE_IMAGE;
$aEventsList[] = 'validate'; $aEventsList[] = 'validate';
$aEventsList[] = 'change'; $aEventsList[] = 'change';
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/edit_image.js'); $oPage->LinkScriptFromAppRoot('js/edit_image.js');
$oDocument = $value; // Value is an ormDocument objectm $oDocument = $value; // Value is an ormDocument objectm
$sDefaultUrl = $oAttDef->Get('default_image'); $sDefaultUrl = $oAttDef->Get('default_image');
if (is_object($oDocument) && !$oDocument->IsEmpty()) { if (is_object($oDocument) && !$oDocument->IsEmpty()) {
@@ -2545,11 +2545,11 @@ HTML;
$sHTMLValue .= '</div></div>'; $sHTMLValue .= '</div></div>';
$sHTMLValue .= '<div>'.$sReloadSpan.'</div>'; // No validation span for this one: it does handle its own validation! $sHTMLValue .= '<div>'.$sReloadSpan.'</div>'; // No validation span for this one: it does handle its own validation!
$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" type=\"hidden\" id=\"$iId\" value=\"\"/>\n"; $sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" type=\"hidden\" id=\"$iId\" value=\"\"/>\n";
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_handler.js'); $oPage->LinkScriptFromAppRoot('js/form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/console_form_handler.js'); $oPage->LinkScriptFromAppRoot('js/console_form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_set.js'); $oPage->LinkScriptFromAppRoot('js/field_set.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_field.js'); $oPage->LinkScriptFromAppRoot('js/form_field.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/subform_field.js'); $oPage->LinkScriptFromAppRoot('js/subform_field.js');
$oPage->add_ready_script( $oPage->add_ready_script(
<<<JS <<<JS
$('#{$iId}_field_set').field_set($sFieldSetOptions); $('#{$iId}_field_set').field_set($sFieldSetOptions);
@@ -2575,9 +2575,9 @@ JS
case 'Set': case 'Set':
case 'TagSet': case 'TagSet':
$sInputType = self::ENUM_INPUT_TYPE_TAGSET; $sInputType = self::ENUM_INPUT_TYPE_TAGSET;
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js'); $oPage->LinkScriptFromAppRoot('js/selectize.min.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css'); $oPage->LinkStylesheetFromAppRoot('css/selectize.default.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js'); $oPage->LinkScriptFromAppRoot('js/jquery.itop-set-widget.js');
$oPage->add_dict_entry('Core:AttributeSet:placeholder'); $oPage->add_dict_entry('Core:AttributeSet:placeholder');
@@ -3452,7 +3452,7 @@ EOF
// Dummy collapsible section created in order to get JS files // Dummy collapsible section created in order to get JS files
$oCollapsibleSection = new CollapsibleSection(''); $oCollapsibleSection = new CollapsibleSection('');
foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) { foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) {
$oPage->add_linked_script($sJSFile); $oPage->LinkScriptFromURI($sJSFile);
} }
} }
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);

View File

@@ -563,8 +563,8 @@ JS
} }
if (!$bEditMode) { if (!$bEditMode) {
$oPage->add_linked_script('../js/dashlet.js'); $oPage->LinkScriptFromAppRoot('js/dashlet.js');
$oPage->add_linked_script('../js/dashboard.js'); $oPage->LinkScriptFromAppRoot('js/dashboard.js');
} }
return $oDashboard; return $oDashboard;
@@ -1118,8 +1118,8 @@ JS
*/ */
protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aExtraParams) protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aExtraParams)
{ {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/blueimp-file-upload/js/jquery.iframe-transport.js'); $oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/blueimp-file-upload/js/jquery.fileupload.js'); $oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier'); $sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}"; $sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";

View File

@@ -326,6 +326,7 @@ class DataTable
$sPagesLinks = implode('', $aPagesToDisplay); $sPagesLinks = implode('', $aPagesToDisplay);
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']'; $sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive'; $sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
$sHtml = $sHtml =
<<<EOF <<<EOF
@@ -333,11 +334,11 @@ class DataTable
<div $sPagerStyle> <div $sPagerStyle>
<table id="pager{$this->iListId}" class="pager"><tr> <table id="pager{$this->iListId}" class="pager"><tr>
<td>$sPages</td> <td>$sPages</td>
<td><img src="../images/first.png" class="first"/></td> <td><img src="{$sAppRootUrl}images/first.png" class="first"/>AAAA</td>
<td><img src="../images/prev.png" class="prev"/></td> <td><img src="{$sAppRootUrl}images/prev.png" class="prev"/></td>
<td><span id="index">$sPagesLinks</span></td> <td><span id="index">$sPagesLinks</span></td>
<td><img src="../images/next.png" class="next"/></td> <td><img src="{$sAppRootUrl}images/next.png" class="next"/></td>
<td><img src="../images/last.png" class="last"/></td> <td><img src="{$sAppRootUrl}images/last.png" class="last"/></td>
<td>$sPageSizeCombo</td> <td>$sPageSizeCombo</td>
<td><span id="loading">&nbsp;</span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input> <td><span id="loading">&nbsp;</span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
</td> </td>

View File

@@ -570,7 +570,7 @@ class DisplayBlock
} else { } else {
// render it as an Ajax (asynchronous) call // render it as an Ajax (asynchronous) call
$oHtml->AddCSSClass("loading"); $oHtml->AddCSSClass("loading");
$oHtml->AddHtml("<p><img src=\"../images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>'); $oHtml->AddHtml("<p><img src=\"".utils::GetAbsoluteUrlAppRoot()."images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>');
$oPage->add_script(' $oPage->add_script('
$.post("ajax.render.php?style='.$this->m_sStyle.'", $.post("ajax.render.php?style='.$this->m_sStyle.'",
{ operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" }, { operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },

View File

@@ -97,8 +97,8 @@ class LoginWebPage extends NiceWebPage
public function SetStyleSheet() public function SetStyleSheet()
{ {
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css'); $this->LinkStylesheetFromAppRoot('css/login.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
} }
/** /**

View File

@@ -233,11 +233,12 @@ class DisplayTemplate
{ {
require_once(APPROOT.'/application/startup.inc.php'); require_once(APPROOT.'/application/startup.inc.php');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sTemplate = '<div class="page_header"> $sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div> <div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1> <h1>$class$: <span class="hilite">$name$</span></h1>
</div> </div>
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right"> <img src="'.$sAppRootUrl.'images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
<itoptabs> <itoptabs>
<itoptab name="Interfaces"> <itoptab name="Interfaces">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock> <itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock>
@@ -350,7 +351,8 @@ class ObjectDetailsTemplate extends DisplayTemplate
if ($iFlags & OPT_ATT_SLAVE) if ($iFlags & OPT_ATT_SLAVE)
{ {
$iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons); $iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>"; $sAppRooturl = utils::GetAbsoluteUrlAppRoot();
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = ''; $sTip = '';
foreach($aReasons as $aRow) foreach($aReasons as $aRow)
{ {

View File

@@ -161,8 +161,8 @@ class UIExtKeyWidget
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '') public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '')
{ {
$sTitle = addslashes($sTitle); $sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js'); $oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js'); $oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_MODIFY) && $bAllowTargetCreation); $bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_MODIFY) && $bAllowTargetCreation);
$bExtensions = true; $bExtensions = true;
@@ -368,7 +368,7 @@ JS
*/ */
public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle) public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle)
{ {
$oPage->add_linked_script('../js/forms-json-utils.js'); $oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation); $bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true; $bExtensions = true;
@@ -477,8 +477,8 @@ JS
$this->bSearchMode = $bSearchMode; $this->bSearchMode = $bSearchMode;
} }
$sTitle = addslashes($sTitle); $sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js'); $oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js'); $oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation); $bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true; $bExtensions = true;

View File

@@ -1446,7 +1446,7 @@ EOF
<<<EOF <<<EOF
function OnTruncatedHistoryToggle(bShowAll) function OnTruncatedHistoryToggle(bShowAll)
{ {
$('#csv_history_reload').html('<img src="../images/indicator.gif"/>'); $('#csv_history_reload').html('<img src="' + GetAbsoluteUrlAppRoot() + 'images/indicator.gif"/>');
$.get(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?{$sAppContext}', {operation: 'displayCSVHistory', showall: bShowAll}, function(data) $.get(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?{$sAppContext}', {operation: 'displayCSVHistory', showall: bShowAll}, function(data)
{ {
$('#$sAjaxDivId').html(data); $('#$sAjaxDivId').html(data);

View File

@@ -397,6 +397,34 @@
</field> </field>
</fields> </fields>
<presentation> <presentation>
<details>
<items>
<item id="date">
<rank>10</rank>
</item>
<item id="title">
<rank>20</rank>
</item>
<item id="message">
<rank>30</rank>
</item>
<item id="contact_id">
<rank>40</rank>
</item>
<item id="trigger_id">
<rank>50</rank>
</item>
<item id="action_id">
<rank>60</rank>
</item>
<item id="read">
<rank>70</rank>
</item>
<item id="url">
<rank>80</rank>
</item>
</items>
</details>
<summary> <summary>
<items> <items>
<item id="date"> <item id="date">

View File

@@ -516,7 +516,7 @@ class ormCaseLog {
$sScript = '<script src="'.$sFileAbsUrl.'"></></script>'; $sScript = '<script src="'.$sFileAbsUrl.'"></></script>';
$sHtml .= $sScript; $sHtml .= $sScript;
} else { } else {
$oP->add_linked_script($sFileAbsUrl); $oP->LinkScriptFromURI($sFileAbsUrl);
} }
} }
} }

View File

@@ -217,7 +217,7 @@ class ormStopWatch
} }
else else
{ {
$aProperties['Elapsed'] = 'running <img src="../images/indicator.gif">'; $aProperties['Elapsed'] = 'running <img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/indicator.gif">';
} }
$aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted); $aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted);

View File

@@ -22,6 +22,9 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
.ibo-object-summary .ibo-panel--title{ .ibo-object-summary .ibo-panel--title{
font-size: $ibo-font-size-250; font-size: $ibo-font-size-250;
} }
.ibo-object-summary .ibo-panel--toolbar{
min-width: 102px;
}
.ibo-object-summary > .ibo-panel--body{ .ibo-object-summary > .ibo-panel--body{
box-shadow: none; box-shadow: none;
max-height: $ibo-notifications--view-all--container--object-summary--panel--body--max-height; max-height: $ibo-notifications--view-all--container--object-summary--panel--body--max-height;
@@ -54,6 +57,17 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
background-color: $ibo-notifications--view-all--item--unread--highlight--background-color; background-color: $ibo-notifications--view-all--item--unread--highlight--background-color;
} }
.ibo-notifications--view-all--read-action, .ibo-notifications--view-all--unread-action {
margin-left: 0 !important;
}
.ibo-notifications--view-all--item--read .ibo-notifications--view-all--read-action {
display: none;
}
.ibo-notifications--view-all--item--unread .ibo-notifications--view-all--unread-action {
display: none;
}
.ibo-notifications--view-all--empty { .ibo-notifications--view-all--empty {
@extend %ibo-fully-centered-content; @extend %ibo-fully-centered-content;
flex-direction: column; flex-direction: column;

View File

@@ -185,6 +185,7 @@ abstract class AbstractAttachmentsRenderer
{ {
$sClass = $this->sObjClass; $sClass = $this->sObjClass;
$sId = $this->iObjKey; $sId = $this->iObjKey;
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$iMaxUploadInBytes = AttachmentPlugIn::GetMaxUploadSize(); $iMaxUploadInBytes = AttachmentPlugIn::GetMaxUploadSize();
$sMaxUploadLabel = AttachmentPlugIn::GetMaxUpload(); $sMaxUploadLabel = AttachmentPlugIn::GetMaxUpload();
$sFileTooBigLabel = Dict::Format('Attachments:Error:FileTooLarge', $sMaxUploadLabel); $sFileTooBigLabel = Dict::Format('Attachments:Error:FileTooLarge', $sMaxUploadLabel);
@@ -195,15 +196,15 @@ abstract class AbstractAttachmentsRenderer
$oAddButton = FileSelectUIBlockFactory::MakeStandard('file', 'file'); $oAddButton = FileSelectUIBlockFactory::MakeStandard('file', 'file');
$oAddButton->SetShowFilename(false); $oAddButton->SetShowFilename(false);
$this->oPage->AddUiBlock($oAddButton); $this->oPage->AddUiBlock($oAddButton);
$this->oPage->add('<span style="display:none;" id="attachment_loading"><img src="../images/indicator.gif"></span> '.$sMaxUploadLabel); $this->oPage->add('<span style="display:none;" id="attachment_loading"><img src="' . $sAppRootUrl . 'images/indicator.gif"></span> ' . $sMaxUploadLabel);
$this->oPage->add('</div>'); $this->oPage->add('</div>');
$this->oPage->add('<div class="ibo-attachment--upload-file--drop-zone-hint ibo-svg-illustration--container">'); $this->oPage->add('<div class="ibo-attachment--upload-file--drop-zone-hint ibo-svg-illustration--container">');
$this->oPage->add(file_get_contents(APPROOT.'images/illustrations/undraw_upload.svg')); $this->oPage->add(file_get_contents(APPROOT.'images/illustrations/undraw_upload.svg'));
$this->oPage->add(Dict::S('UI:Attachments:DropYourFileHint').'</div>'); $this->oPage->add(Dict::S('UI:Attachments:DropYourFileHint').'</div>');
$this->oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/blueimp-file-upload/js/jquery.iframe-transport.js'); $this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
$this->oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/blueimp-file-upload/js/jquery.fileupload.js'); $this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
$this->oPage->add_ready_script( $this->oPage->add_ready_script(
<<<JS <<<JS
@@ -342,7 +343,7 @@ abstract class AbstractAttachmentsRenderer
$('.attachment a[href="'+sSrc+'"]').parent().addClass('image-in-use').find('img').wrap('<div class="image-in-use-wrapper" style="position:relative;display:inline-block;"></div>'); $('.attachment a[href="'+sSrc+'"]').parent().addClass('image-in-use').find('img').wrap('<div class="image-in-use-wrapper" style="position:relative;display:inline-block;"></div>');
}); });
}); });
$('.image-in-use-wrapper').append('<div style="position:absolute;top:0;left:0;"><img src="../images/transp-lock.png"></div>'); $('.image-in-use-wrapper').append('<div style="position:absolute;top:0;left:0;"><img src="' + GetAbsoluteUrlModulesRoot() + 'images/transp-lock.png"></div>');
}, 200 ); }, 200 );
JS JS
); );

View File

@@ -110,10 +110,10 @@ ApplicationMenu::CheckMenuIdEnabled('ConfigEditor');
$oP = new iTopWebPage(Dict::S('config-edit-title')); $oP = new iTopWebPage(Dict::S('config-edit-title'));
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/'); $oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
$sAceDir = 'node_modules/ace-builds/src-min/'; $sAceDir = 'node_modules/ace-builds/src-min/';
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sAceDir.'ace.js'); $oP->LinkScriptFromAppRoot($sAceDir.'ace.js');
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sAceDir.'mode-php.js'); $oP->LinkScriptFromAppRoot($sAceDir.'mode-php.js');
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sAceDir.'theme-eclipse.js'); $oP->LinkScriptFromAppRoot($sAceDir.'theme-eclipse.js');
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sAceDir.'ext-searchbox.js'); $oP->LinkScriptFromAppRoot($sAceDir.'ext-searchbox.js');
try { try {
$sOperation = utils::ReadParam('operation', ''); $sOperation = utils::ReadParam('operation', '');

View File

@@ -17,7 +17,7 @@ class HubConnectorPage extends NiceWebPage
$sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images'; $sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images';
$sUserPrefs = appUserPreferences::GetAsJSON(); $sUserPrefs = appUserPreferences::GetAsJSON();
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js'); $this->LinkScriptFromAppRoot('js/utils.js');
$this->add_script(<<<JS $this->add_script(<<<JS
var oUserPreferences = $sUserPrefs; var oUserPreferences = $sUserPrefs;
JS JS

View File

@@ -57,7 +57,7 @@ function DisplayStatus(WebPage $oPage)
function DoLanding(WebPage $oPage) function DoLanding(WebPage $oPage)
{ {
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css'); $oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
$oPage->add('<table class="module-selection-banner"><tr>'); $oPage->add('<table class="module-selection-banner"><tr>');
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png'; $sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
$oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>'); $oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>');
@@ -138,7 +138,7 @@ function DoInstall(WebPage $oPage)
$sUID = hash('sha256', rand()); $sUID = hash('sha256', rand());
file_put_contents(utils::GetDataPath().'hub/compile_authent', $sUID); file_put_contents(utils::GetDataPath().'hub/compile_authent', $sUID);
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css'); $oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
$oPage->add('<table class="module-selection-banner"><tr>'); $oPage->add('<table class="module-selection-banner"><tr>');
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png'; $sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
$oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>'); $oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>');
@@ -214,7 +214,7 @@ function DoInstall(WebPage $oPage)
$oPage->add('</div>'); // module-selection-body $oPage->add('</div>'); // module-selection-body
$oPage->add_linked_stylesheet('../css/font-awesome/css/all.min.css'); $oPage->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$oPage->add('<div id="hub_installation_widget"></div>'); $oPage->add('<div id="hub_installation_widget"></div>');
@@ -263,8 +263,8 @@ try {
} }
$oPage = new SetupPage(''); // Title will be set later, depending on $sOperation $oPage = new SetupPage(''); // Title will be set later, depending on $sOperation
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js'); $oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css'); $oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$oPage->add_style(<<<CSS $oPage->add_style(<<<CSS
div.choice { margin: 0.5em;} div.choice { margin: 0.5em;}

View File

@@ -305,9 +305,9 @@ try {
$sCloseUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/black-close.svg'; $sCloseUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/black-close.svg';
$oPage = new HubConnectorPage(Dict::S('iTopHub:Connect')); $oPage = new HubConnectorPage(Dict::S('iTopHub:Connect'));
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js'); $oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css'); $oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css'); $oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
$aDataToPost = MakeDataToPost($sTargetRoute); $aDataToPost = MakeDataToPost($sTargetRoute);

View File

@@ -1620,7 +1620,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'UI:Newsroom:Preferences' => 'Préférences du centre d\'information', 'UI:Newsroom:Preferences' => 'Préférences du centre d\'information',
'UI:Newsroom:ConfigurationLink' => 'Configuration', 'UI:Newsroom:ConfigurationLink' => 'Configuration',
'UI:Newsroom:ResetCache' => 'Ràz du cache', 'UI:Newsroom:ResetCache' => 'Ràz du cache',
'UI:Newsroom:ResetCache:Success:Message' => 'Le cache a été réinitialisé avec succès', 'UI:Newsroom:ResetCache:Success:Message' => 'Le cache de la newsroom a été réinitialisé avec succès',
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Afficher les messages de %1$s', 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Afficher les messages de %1$s',
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Afficher au plus %1$s messages dans le menu %2$s.', 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Afficher au plus %1$s messages dans le menu %2$s.',
)); ));

View File

@@ -363,7 +363,6 @@ $(function()
var sKey = this._makeCacheKey(idx); var sKey = this._makeCacheKey(idx);
localStorage.removeItem(sKey); localStorage.removeItem(sKey);
} }
CombodoToast.OpenSuccessToast(Dict.S('UI:Newsroom:ResetCache:Success:Message'));
}, },
_makeCacheKey: function(idxProvider) _makeCacheKey: function(idxProvider)
{ {

View File

@@ -15,6 +15,8 @@ $('body').on('itop.notification.deleted', '.ibo-notifications--view-all--contain
$('.ibo-notifications--view-all--unread-action').attr('disabled', 'disabled'); $('.ibo-notifications--view-all--unread-action').attr('disabled', 'disabled');
$('.ibo-notifications--view-all--delete-action').attr('disabled', 'disabled'); $('.ibo-notifications--view-all--delete-action').attr('disabled', 'disabled');
} }
$('#ibo-navigation-menu--notifications-menu').newsroom_menu("clearCache");
}); });
let fReadUnreadDisabled = function() { let fReadUnreadDisabled = function() {
@@ -28,6 +30,8 @@ let fReadUnreadDisabled = function() {
$('.ibo-notifications--view-all--read-action').removeAttr('disabled'); $('.ibo-notifications--view-all--read-action').removeAttr('disabled');
$('.ibo-notifications--view-all--unread-action').removeAttr('disabled'); $('.ibo-notifications--view-all--unread-action').removeAttr('disabled');
} }
$('#ibo-navigation-menu--notifications-menu').newsroom_menu("clearCache");
} }
$('body').on('itop.notification.read itop.notification.unread', '.ibo-notifications--view-all--container', fReadUnreadDisabled); $('body').on('itop.notification.read itop.notification.unread', '.ibo-notifications--view-all--container', fReadUnreadDisabled);

View File

@@ -350,7 +350,7 @@ try
case 'stimulus': // Form displayed when applying a stimulus (state change) case 'stimulus': // Form displayed when applying a stimulus (state change)
case 'apply_stimulus': // Form displayed when applying a stimulus (state change) case 'apply_stimulus': // Form displayed when applying a stimulus (state change)
foreach (ObjectController::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) { foreach (ObjectController::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) {
$oP->add_linked_script("../$sJsFileRelPath"); $oP->LinkScriptFromAppRoot($sJsFileRelPath);
} }
break; break;
} }
@@ -651,7 +651,7 @@ try
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $sDescription, '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES); $oP->SetBreadCrumbEntry($sPageId, $sLabel, $sDescription, '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->add("<div style=\"padding: 10px;\">\n"); $oP->add("<div style=\"padding: 10px;\">\n");
$oP->add("<div class=\"header_message\" id=\"full_text_progress\" style=\"position: fixed; background-color: #cccccc; opacity: 0.7; padding: 1.5em;\">\n"); $oP->add("<div class=\"header_message\" id=\"full_text_progress\" style=\"position: fixed; background-color: #cccccc; opacity: 0.7; padding: 1.5em;\">\n");
$oP->add('<img id="full_text_indicator" src="../images/indicator.gif">&nbsp;<span style="padding: 1.5em;">'.Dict::Format('UI:Search:Ongoing', utils::EscapeHtml($sFullText)).'</span>'); $oP->add('<img id="full_text_indicator" src="' . utils::GetAbsoluteUrlAppRoot() . 'images/indicator.gif">&nbsp;<span style="padding: 1.5em;">'.Dict::Format('UI:Search:Ongoing', utils::EscapeHtml($sFullText)).'</span>');
$oP->add("</div>\n"); $oP->add("</div>\n");
$oP->add("<div id=\"full_text_results\">\n"); $oP->add("<div id=\"full_text_results\">\n");
$oP->add("<div id=\"full_text_progress_placeholder\" style=\"padding: 1.5em;\">&nbsp;</div>\n"); $oP->add("<div id=\"full_text_progress_placeholder\" style=\"padding: 1.5em;\">&nbsp;</div>\n");

View File

@@ -33,11 +33,11 @@ ApplicationMenu::CheckMenuIdEnabled('UniversalSearchMenu');
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$oP = new iTopWebPage(Dict::S('UI:UniversalSearchTitle')); $oP = new iTopWebPage(Dict::S('UI:UniversalSearchTitle'));
$oP->add_linked_script("../js/forms-json-utils.js"); $oP->LinkScriptFromAppRoot("js/forms-json-utils.js");
$oP->add_linked_script("../js/wizardhelper.js"); $oP->LinkScriptFromAppRoot("js/wizardhelper.js");
$oP->add_linked_script("../js/wizard.utils.js"); $oP->LinkScriptFromAppRoot("js/wizard.utils.js");
$oP->add_linked_script("../js/extkeywidget.js"); $oP->LinkScriptFromAppRoot("js/extkeywidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js"); $oP->LinkScriptFromAppRoot("js/jquery.blockUI.js");
// From now on the context is limited to the the selected organization ?? // From now on the context is limited to the the selected organization ??

View File

@@ -1375,7 +1375,7 @@ JS
<<<EOF <<<EOF
$('.search-class-$sClassName button').prop('disabled', true); $('.search-class-$sClassName button').prop('disabled', true);
$('.search-class-$sClassName h2').append('&nbsp;<img id="indicator" src="../images/indicator.gif">'); $('.search-class-$sClassName h2').append('&nbsp;<img id="indicator" src="' + GetAbsoluteUrlAppRoot() + 'images/indicator.gif">');
var oParams = {operation: 'full_text_search_enlarge', class: '$sClassName', text: '$sFullTextJS'}; var oParams = {operation: 'full_text_search_enlarge', class: '$sClassName', text: '$sFullTextJS'};
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) { $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
$('.search-class-$sClassName').html(data); $('.search-class-$sClassName').html(data);
@@ -1532,6 +1532,7 @@ EOF
case 'xlsx_export_dialog': case 'xlsx_export_dialog':
DeprecatedCallsLog::NotifyDeprecatedPhpEndpoint('Use "export_*" operations instead of "'.$operation.'"'); DeprecatedCallsLog::NotifyDeprecatedPhpEndpoint('Use "export_*" operations instead of "'.$operation.'"');
$sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->SetContentType('text/html'); $oPage->SetContentType('text/html');
$oPage->add( $oPage->add(
<<<EOF <<<EOF
@@ -1561,11 +1562,11 @@ EOF
padding-left: 16px; padding-left: 16px;
cursor: pointer; cursor: pointer;
font-size: 10pt; font-size: 10pt;
background: url(../images/minus.gif) 0 2px no-repeat; background: url({$sAppRootUrl}images/minus.gif) 0 2px no-repeat;
} }
.statistics > div.closed { .statistics > div.closed {
padding-left: 16px; padding-left: 16px;
background: url(../images/plus.gif) 0 2px no-repeat; background: url({$sAppRootUrl}images/plus.gif) 0 2px no-repeat;
} }
.statistics .closed .stats-data { .statistics .closed .stats-data {
@@ -1594,7 +1595,7 @@ EOF
); );
$sJSLabels = json_encode($aLabels); $sJSLabels = json_encode($aLabels);
$sFilter = addslashes($sFilter); $sFilter = addslashes($sFilter);
$sJSPageUrl = addslashes(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php'); $sJSPageUrl = addslashes($sAppRootUrl.'pages/ajax.render.php');
$oPage->add_ready_script("$('#XlsxExportDlg').xlsxexporter({filter: '$sFilter', labels: $sJSLabels, ajax_page_url: '$sJSPageUrl'});"); $oPage->add_ready_script("$('#XlsxExportDlg').xlsxexporter({filter: '$sFilter', labels: $sJSLabels, ajax_page_url: '$sJSPageUrl'});");
break; break;
@@ -2206,9 +2207,10 @@ EOF
case 'cke_browse': case 'cke_browse':
$oPage = new NiceWebPage(Dict::S('UI:BrowseInlineImages')); $oPage = new NiceWebPage(Dict::S('UI:BrowseInlineImages'));
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/magnific-popup.css'); $oPage->LinkStylesheetFromAppRoot('node_modules/magnific-popup/dist/magnific-popup.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/jquery.magnific-popup.min.js'); $oPage->LinkScriptFromAppRoot('node_modules/magnific-popup/dist/jquery.magnific-popup.min.js');
$sImgUrl = utils::GetAbsoluteUrlAppRoot().INLINEIMAGE_DOWNLOAD_URL; $sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sImgUrl = $sAppRootUrl.INLINEIMAGE_DOWNLOAD_URL;
/** @noinspection SuspiciousAssignmentsInspection cke_upload_and_browse and cke_browse are chained */ /** @noinspection SuspiciousAssignmentsInspection cke_upload_and_browse and cke_browse are chained */
$sTempId = utils::ReadParam('temp_id', '', false, 'transaction_id'); $sTempId = utils::ReadParam('temp_id', '', false, 'transaction_id');
@@ -2236,7 +2238,7 @@ EOF
} }
} }
$sPostUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?CKEditorFuncNum='.$sCKEditorFuncNum; $sPostUrl = $sAppRootUrl.'pages/ajax.render.php?CKEditorFuncNum='.$sCKEditorFuncNum;
$oPage->add_style( $oPage->add_style(
<<<EOF <<<EOF
@@ -2304,7 +2306,7 @@ EOF
$oPage->add_ready_script( $oPage->add_ready_script(
<<<EOF <<<EOF
$('#upload_button').on('change', function() { $('#upload_button').on('change', function() {
$('#upload_status').html('<img src="../images/indicator.gif">'); $('#upload_status').html('<img src="{$sAppRootUrl}images/indicator.gif">');
$('#upload_form').submit(); $('#upload_form').submit();
$(this).prop('disabled', true); $(this).prop('disabled', true);
}); });

View File

@@ -281,7 +281,7 @@ try
$oAllCategoriesDashlet $oAllCategoriesDashlet
->AddCSSClasses(['ibo-dashlet--is-inline', 'ibo-dashlet-badge']) ->AddCSSClasses(['ibo-dashlet--is-inline', 'ibo-dashlet-badge'])
->AddSubBlock(DashletFactory::MakeForDashletBadge( ->AddSubBlock(DashletFactory::MakeForDashletBadge(
'../images/icons/icons8-audit.svg', utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-audit.svg',
utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit", utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit",
$iCategoryCount, $iCategoryCount,
Dict::S('UI:Audit:Interactive:Selection:BadgeAll') Dict::S('UI:Audit:Interactive:Selection:BadgeAll')
@@ -304,7 +304,7 @@ try
/** @var AuditDomain $oAuditDomain */ /** @var AuditDomain $oAuditDomain */
while($oAuditDomain = $oDomainSet->Fetch()) { while($oAuditDomain = $oDomainSet->Fetch()) {
$sDomainUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit&domain=".$oAuditDomain->GetKey(); $sDomainUrl = utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit&domain=".$oAuditDomain->GetKey();
$sIconUrl = '../images/icons/icons8-puzzle.svg'; $sIconUrl = utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-puzzle.svg';
/** @var \ormDocument $oImage */ /** @var \ormDocument $oImage */
$oImage = $oAuditDomain->Get('icon'); $oImage = $oAuditDomain->Get('icon');
if (!$oImage->IsEmpty()) { if (!$oImage->IsEmpty()) {
@@ -357,9 +357,9 @@ try
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle)); $oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle));
$oP->AddUiBlock(new Text($sSubTitle)); $oP->AddUiBlock(new Text($sSubTitle));
$oTotalBlock = DashletFactory::MakeForDashletBadge('../images/icons/icons8-audit.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsAudited')); $oTotalBlock = DashletFactory::MakeForDashletBadge(utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-audit.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsAudited'));
$oErrorBlock = DashletFactory::MakeForDashletBadge('../images/icons/icons8-delete.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsInError')); $oErrorBlock = DashletFactory::MakeForDashletBadge(utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-delete.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsInError'));
$oWorkingBlock = DashletFactory::MakeForDashletBadge('../images/icons/icons8-checkmark.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsValidated')); $oWorkingBlock = DashletFactory::MakeForDashletBadge(utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-checkmark.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsValidated'));
$aCSSClasses = ['ibo-dashlet--is-inline', 'ibo-dashlet-badge']; $aCSSClasses = ['ibo-dashlet--is-inline', 'ibo-dashlet-badge'];
@@ -436,7 +436,7 @@ try
foreach ($aErrors as $aErrorRow) { foreach ($aErrors as $aErrorRow) {
$aObjectsWithErrors[$aErrorRow['id']] = true; $aObjectsWithErrors[$aErrorRow['id']] = true;
} }
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\">$iErrorsCount</a> <a href=\"?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\"><img src=\"../images/icons/icons8-export-csv.svg\" class=\"ibo-audit--audit-line--csv-download\"></a>"; $aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\">$iErrorsCount</a> <a href=\"?operation=csv&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\"><img src=\"" . utils::GetAbsoluteUrlAppRoot() . "images/icons/icons8-export-csv.svg\" class=\"ibo-audit--audit-line--csv-download\"></a>";
$aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount)); $aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount));
$aRow['class'] = $oAuditCategory->GetReportColor($iCount, $iErrorsCount); $aRow['class'] = $oAuditCategory->GetReportColor($iCount, $iErrorsCount);
} }

View File

@@ -400,6 +400,7 @@ try {
$iUnchanged = 0; $iUnchanged = 0;
$aTableData = []; $aTableData = [];
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
foreach ($aRes as $iLine => $aResRow) { foreach ($aRes as $iLine => $aResRow) {
$aTableRow = []; $aTableRow = [];
@@ -414,7 +415,7 @@ try {
$sFinalClass = $aResRow['finalclass']; $sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$sUrl = $oObj->GetHyperlink(); $sUrl = $oObj->GetHyperlink();
$sStatus = '<img src="../images/unchanged.png" title="'.Dict::S('UI:CSVReport-Icon-Unchanged').'">'; $sStatus = '<img src="' . $sAppRootUrl . 'images/unchanged.png" title="'.Dict::S('UI:CSVReport-Icon-Unchanged').'">';
$sCSSRowClass = 'ibo-csv-import--row-unchanged'; $sCSSRowClass = 'ibo-csv-import--row-unchanged';
break; break;
@@ -423,7 +424,7 @@ try {
$sFinalClass = $aResRow['finalclass']; $sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$sUrl = $oObj->GetHyperlink(); $sUrl = $oObj->GetHyperlink();
$sStatus = '<img src="../images/modified.png" title="'.Dict::S('UI:CSVReport-Icon-Modified').'">'; $sStatus = '<img src="' . $sAppRootUrl . 'images/modified.png" title="'.Dict::S('UI:CSVReport-Icon-Modified').'">';
$sCSSRowClass = 'ibo-csv-import--row-modified'; $sCSSRowClass = 'ibo-csv-import--row-modified';
break; break;
@@ -432,7 +433,7 @@ try {
$sFinalClass = $aResRow['finalclass']; $sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$sUrl = $oObj->GetHyperlink(); $sUrl = $oObj->GetHyperlink();
$sStatus = '<img src="../images/delete.png" title="'.Dict::S('UI:CSVReport-Icon-Missing').'">'; $sStatus = '<img src="' . $sAppRootUrl . 'images/delete.png" title="'.Dict::S('UI:CSVReport-Icon-Missing').'">';
$sCSSRowClass = 'ibo-csv-import--row-modified'; $sCSSRowClass = 'ibo-csv-import--row-modified';
if ($bSimulate) { if ($bSimulate) {
$sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate'); $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate');
@@ -443,7 +444,7 @@ try {
case 'RowStatus_NewObj': case 'RowStatus_NewObj':
$iCreated++; $iCreated++;
$sStatus = '<img src="../images/added.png" title="'.Dict::S('UI:CSVReport-Icon-Created').'">'; $sStatus = '<img src="' . $sAppRootUrl . 'images/added.png" title="'.Dict::S('UI:CSVReport-Icon-Created').'">';
$sCSSRowClass = 'ibo-csv-import--row-added'; $sCSSRowClass = 'ibo-csv-import--row-added';
if ($bSimulate) { if ($bSimulate) {
$sMessage = Dict::S('UI:CSVReport-Object-ToCreate'); $sMessage = Dict::S('UI:CSVReport-Object-ToCreate');
@@ -585,21 +586,21 @@ HTML;
$oMulticolumn->AddCSSClass('ml-1'); $oMulticolumn->AddCSSClass('ml-1');
$oForm->AddSubBlock($oMulticolumn); $oForm->AddSubBlock($oMulticolumn);
$oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="../images/unchanged.png">&nbsp;'.sprintf($aDisplayFilters['unchanged'], $iUnchanged), '', "1", "show_unchanged", "checkbox"); $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="' . $sAppRootUrl . 'images/unchanged.png">&nbsp;'.sprintf($aDisplayFilters['unchanged'], $iUnchanged), '', "1", "show_unchanged", "checkbox");
$oCheckBoxUnchanged->GetInput()->SetIsChecked(true); $oCheckBoxUnchanged->GetInput()->SetIsChecked(true);
$oCheckBoxUnchanged->SetBeforeInput(false); $oCheckBoxUnchanged->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged)); $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged));
$oPage->add_ready_script("$('#show_unchanged').on('click', function(){ToggleRows('ibo-csv-import--row-unchanged')})"); $oPage->add_ready_script("$('#show_unchanged').on('click', function(){ToggleRows('ibo-csv-import--row-unchanged')})");
$oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="../images/modified.png">&nbsp;'.sprintf($aDisplayFilters['modified'], $iModified), '', "1", "show_modified", "checkbox"); $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="' . $sAppRootUrl . 'images/modified.png">&nbsp;'.sprintf($aDisplayFilters['modified'], $iModified), '', "1", "show_modified", "checkbox");
$oCheckBoxUnchanged->GetInput()->SetIsChecked(true); $oCheckBoxUnchanged->GetInput()->SetIsChecked(true);
$oCheckBoxUnchanged->SetBeforeInput(false); $oCheckBoxUnchanged->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged)); $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged));
$oPage->add_ready_script("$('#show_modified').on('click', function(){ToggleRows('ibo-csv-import--row-modified')})"); $oPage->add_ready_script("$('#show_modified').on('click', function(){ToggleRows('ibo-csv-import--row-modified')})");
$oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="../images/added.png">&nbsp;'.sprintf($aDisplayFilters['added'], $iCreated), '', "1", "show_created", "checkbox"); $oCheckBoxUnchanged = InputUIBlockFactory::MakeForInputWithLabel('<img src="' . $sAppRootUrl . 'images/added.png">&nbsp;'.sprintf($aDisplayFilters['added'], $iCreated), '', "1", "show_created", "checkbox");
$oCheckBoxUnchanged->GetInput()->SetIsChecked(true); $oCheckBoxUnchanged->GetInput()->SetIsChecked(true);
$oCheckBoxUnchanged->SetBeforeInput(false); $oCheckBoxUnchanged->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox'); $oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');

View File

@@ -133,7 +133,7 @@ function ValidateOtherSettings()
} }
else else
{ {
$('#v_default_page_size').html('<img src="../images/validation_error.png"/>'); $('#v_default_page_size').html('<img src="' + GetAbsoluteUrlAppRoot() + 'images/validation_error.png"/>');
$('#ibo-misc-settings-submit').prop('disabled', true); $('#ibo-misc-settings-submit').prop('disabled', true);
return false; return false;
} }
@@ -315,7 +315,11 @@ JS
// - Reset button // - Reset button
$oNewsroomResetCacheButton = ButtonUIBlockFactory::MakeForAlternativeDestructiveAction(Dict::S('UI:Newsroom:ResetCache')); $oNewsroomResetCacheButton = ButtonUIBlockFactory::MakeForAlternativeDestructiveAction(Dict::S('UI:Newsroom:ResetCache'));
$oNewsroomResetCacheButton->SetOnClickJsCode("$('#ibo-navigation-menu--notifications-menu').newsroom_menu('clearCache')"); $oNewsroomResetCacheButton->SetOnClickJsCode(<<<JS
$('#ibo-navigation-menu--notifications-menu').newsroom_menu('clearCache')
CombodoToast.OpenSuccessToast(Dict.S('UI:Newsroom:ResetCache:Success:Message'));
JS
);
$oNewsroomToolbar->AddSubBlock($oNewsroomResetCacheButton); $oNewsroomToolbar->AddSubBlock($oNewsroomResetCacheButton);
// - Cancel button // - Cancel button
$oNewsroomCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel')); $oNewsroomCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel'));
@@ -417,7 +421,7 @@ JS
$oUserPicturePlaceHolderBlock = new Panel(Dict::S('UI:Preferences:ChooseAPlaceholder'), array(), 'grey', 'ibo-user-picture-placeholder'); $oUserPicturePlaceHolderBlock = new Panel(Dict::S('UI:Preferences:ChooseAPlaceholder'), array(), 'grey', 'ibo-user-picture-placeholder');
$sUserPicturesFolder = '../images/user-pictures/'; $sUserPicturesFolder = utils::GetAbsoluteUrlAppRoot() . 'images/user-pictures/';
$sUserDefaultPicture = appUserPreferences::GetPref('user_picture_placeholder', 'default-placeholder.png'); $sUserDefaultPicture = appUserPreferences::GetPref('user_picture_placeholder', 'default-placeholder.png');
$sUserPicturePlaceHolderHtml = ''; $sUserPicturePlaceHolderHtml = '';
$sUserPicturePlaceHolderHtml .= '<p>'.Dict::S('UI:Preferences:ChooseAPlaceholder+').'</p> <div class="ibo-preferences--user-preferences--picture-placeholder">'; $sUserPicturePlaceHolderHtml .= '<p>'.Dict::S('UI:Preferences:ChooseAPlaceholder+').'</p> <div class="ibo-preferences--user-preferences--picture-placeholder">';
@@ -916,7 +920,12 @@ try {
} }
if ($bProvidersModified) if ($bProvidersModified)
{ {
$oPage->add_ready_script('$(".itop-newsroom_menu").newsroom_menu("clearCache");'); $oPage->add_ready_script(
<<<JS
$('#ibo-navigation-menu--notifications-menu').newsroom_menu("clearCache");
CombodoToast.OpenSuccessToast(Dict.S('UI:Newsroom:ResetCache:Success:Message'));
JS
);
} }
DisplayPreferences($oPage); DisplayPreferences($oPage);
break; break;

View File

@@ -37,11 +37,11 @@ try
// Main program // Main program
// //
$oP = new iTopWebPage(Dict::S('Menu:TagAdminMenu+')); $oP = new iTopWebPage(Dict::S('Menu:TagAdminMenu+'));
$oP->add_linked_script("../js/forms-json-utils.js"); $oP->LinkScriptFromAppRoot("js/forms-json-utils.js");
$oP->add_linked_script("../js/wizardhelper.js"); $oP->LinkScriptFromAppRoot("js/wizardhelper.js");
$oP->add_linked_script("../js/wizard.utils.js"); $oP->LinkScriptFromAppRoot("js/wizard.utils.js");
$oP->add_linked_script("../js/extkeywidget.js"); $oP->LinkScriptFromAppRoot("js/extkeywidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js"); $oP->LinkScriptFromAppRoot("js/jquery.blockUI.js");
$sBaseClass = 'TagSetFieldData'; $sBaseClass = 'TagSetFieldData';
$sClass = utils::ReadParam('class', '', false, 'class'); $sClass = utils::ReadParam('class', '', false, 'class');

View File

@@ -39,14 +39,14 @@ class SetupPage extends NiceWebPage
public function __construct($sTitle) public function __construct($sTitle)
{ {
parent::__construct($sTitle); parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js"); $this->LinkScriptFromAppRoot("js/jquery.blockUI.js");
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/@popperjs/core/dist/umd/popper.js'); $this->LinkScriptFromAppRoot('node_modules/@popperjs/core/dist/umd/popper.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy-bundle.umd.js'); $this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.js');
$this->add_linked_script("../setup/setup.js"); $this->LinkScriptFromAppRoot("setup/setup.js");
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css'); $this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy.css'); $this->LinkStylesheetFromAppRoot('node_modules/tippy.js/dist/tippy.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/animations/shift-away-subtle.css'); $this->LinkStylesheetFromAppRoot('node_modules/tippy.js/animations/shift-away-subtle.css');
$this->LoadTheme(); $this->LoadTheme();
$this->add_saas("css/setup.scss"); $this->add_saas("css/setup.scss");

View File

@@ -217,7 +217,7 @@ HTML;
} }
} }
} }
$oPage->add_linked_script('../setup/setup.js'); $oPage->LinkScriptFromAppRoot('setup/setup.js');
$oPage->add_script("function CanMoveForward()\n{\n".$oStep->JSCanMoveForward()."\n}\n"); $oPage->add_script("function CanMoveForward()\n{\n".$oStep->JSCanMoveForward()."\n}\n");
$oPage->add_script("function CanMoveBackward()\n{\n".$oStep->JSCanMoveBackward()."\n}\n"); $oPage->add_script("function CanMoveBackward()\n{\n".$oStep->JSCanMoveBackward()."\n}\n");
$oPage->add('<form id="wiz_form" class="ibo-setup--wizard" method="post">'); $oPage->add('<form id="wiz_form" class="ibo-setup--wizard" method="post">');

View File

@@ -2307,7 +2307,7 @@ class WizStepSummary extends WizardStep
$oPage->add('<fieldset id="installation_progress"><legend>Progress of the installation</legend>'); $oPage->add('<fieldset id="installation_progress"><legend>Progress of the installation</legend>');
$oPage->add('<div id="progress_content">'); $oPage->add('<div id="progress_content">');
$oPage->add_linked_script('../setup/jquery.progression.js'); $oPage->LinkScriptFromAppRoot('setup/jquery.progression.js');
$oPage->add('<p class="center"><span id="setup_msg">Ready to start...</span></p><div style="display:block;margin-left: auto; margin-right:auto;" id="progress">0%</div>'); $oPage->add('<p class="center"><span id="setup_msg">Ready to start...</span></p><div style="display:block;margin-left: auto; margin-right:auto;" id="progress">0%</div>');
$oPage->add('</div>'); // progress_content $oPage->add('</div>'); // progress_content
$oPage->add('</fieldset>'); $oPage->add('</fieldset>');

View File

@@ -55,7 +55,6 @@ class FormHelper
*/ */
public static function DisableAttributeBlobInputs(string $sClassName, array &$aExtraParams): void public static function DisableAttributeBlobInputs(string $sClassName, array &$aExtraParams): void
{ {
// Initialize extra params array // Initialize extra params array
if (!array_key_exists('fieldsFlags', $aExtraParams)) { if (!array_key_exists('fieldsFlags', $aExtraParams)) {
$aExtraParams['fieldsFlags'] = []; $aExtraParams['fieldsFlags'] = [];
@@ -64,13 +63,13 @@ class FormHelper
$aExtraParams['fieldsComments'] = []; $aExtraParams['fieldsComments'] = [];
} }
// Iterate throw class attributes... // Iterate through class attributes...
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) { foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
// Set attribute blobs in read only // Set attribute blobs in read only
if ($oAttDef instanceof AttributeBlob) { if ($oAttDef instanceof AttributeBlob) {
$aExtraParams['fieldsFlags'][$sAttCode] = OPT_ATT_READONLY; $aExtraParams['fieldsFlags'][$sAttCode] = OPT_ATT_READONLY;
$aExtraParams['fieldsComments'][$sAttCode] = '&nbsp;<img src="../images/transp-lock.png" style="vertical-align:middle" title="'.utils::EscapeHtml(Dict::S('UI:UploadNotSupportedInThisMode')).'"/>'; $aExtraParams['fieldsComments'][$sAttCode] = '&nbsp;<img src="' . $sAppRootUrl . 'images/transp-lock.png" style="vertical-align:middle" title="'.utils::EscapeHtml(Dict::S('UI:UploadNotSupportedInThisMode')).'"/>';
} }
} }
} }

View File

@@ -62,7 +62,7 @@ class WebResourcesHelper
//when ckeditor is loaded in ajax, CKEDITOR_BASEPATH is not well defined (this constant is used to load additional js) //when ckeditor is loaded in ajax, CKEDITOR_BASEPATH is not well defined (this constant is used to load additional js)
$oPage->add_script("if (! window.CKEDITOR_BASEPATH) { var CKEDITOR_BASEPATH = '".utils::GetAbsoluteUrlAppRoot()."js/ckeditor/';}"); $oPage->add_script("if (! window.CKEDITOR_BASEPATH) { var CKEDITOR_BASEPATH = '".utils::GetAbsoluteUrlAppRoot()."js/ckeditor/';}");
foreach (static::GetJSFilesRelPathsForCKEditor() as $sFile) { foreach (static::GetJSFilesRelPathsForCKEditor() as $sFile) {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sFile); $oPage->LinkScriptFromAppRoot($sFile);
} }
} }
@@ -93,11 +93,11 @@ class WebResourcesHelper
public static function EnableC3JSToWebPage(WebPage &$oPage): void public static function EnableC3JSToWebPage(WebPage &$oPage): void
{ {
foreach (static::GetCSSFilesRelPathsForC3JS() as $sFile) { foreach (static::GetCSSFilesRelPathsForC3JS() as $sFile) {
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().$sFile); $oPage->LinkStylesheetFromAppRoot($sFile);
} }
foreach (static::GetJSFilesRelPathsForC3JS() as $sFile) { foreach (static::GetJSFilesRelPathsForC3JS() as $sFile) {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sFile); $oPage->LinkScriptFromAppRoot($sFile);
} }
} }
@@ -135,13 +135,13 @@ class WebResourcesHelper
*/ */
public static function EnableSimpleGraphInWebPage(WebPage &$oPage): void public static function EnableSimpleGraphInWebPage(WebPage &$oPage): void
{ {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/raphael-min.js'); $oPage->LinkScriptFromAppRoot('js/raphael-min.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/fraphael.js'); $oPage->LinkScriptFromAppRoot('js/fraphael.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery-contextmenu/src/jquery.contextMenu.css'); $oPage->LinkStylesheetFromAppRoot('node_modules/jquery-contextmenu/src/jquery.contextMenu.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery-contextmenu/src/jquery.contextMenu.js'); $oPage->LinkScriptFromAppRoot('node_modules/jquery-contextmenu/src/jquery.contextMenu.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js'); $oPage->LinkScriptFromAppRoot('js/jquery.positionBy.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.popupmenu.js'); $oPage->LinkScriptFromAppRoot('js/jquery.popupmenu.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.mousewheel.js'); $oPage->LinkScriptFromAppRoot('js/jquery.mousewheel.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/simple_graph.js'); $oPage->LinkScriptFromAppRoot('js/simple_graph.js');
} }
} }

View File

@@ -26,10 +26,10 @@ class ErrorPage extends NiceWebPage
{ {
$oKpi = new ExecutionKPI(); $oKpi = new ExecutionKPI();
parent::__construct($sTitle); parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js"); $this->LinkScriptFromAppRoot("js/jquery.blockUI.js");
$this->add_linked_script("../setup/setup.js"); $this->LinkScriptFromAppRoot("setup/setup.js");
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css'); $this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$this->add_saas("css/setup.scss"); $this->add_saas("css/setup.scss");
$oKpi->ComputeStats(get_class($this).' creation', 'ErrorPage'); $oKpi->ComputeStats(get_class($this).' creation', 'ErrorPage');
} }
@@ -58,7 +58,7 @@ class ErrorPage extends NiceWebPage
if(utils::IsEasterEggAllowed()) if(utils::IsEasterEggAllowed())
{ {
$this->add('<div class="message message-valid">'.Dict::S('UI:ErrorPage:UnstableVersion').'</div>'); $this->add('<div class="message message-valid">'.Dict::S('UI:ErrorPage:UnstableVersion').'</div>');
$this->add('<img src="../images/alpha-fatal-error.gif">'); $this->add('<img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/alpha-fatal-error.gif">');
$this->add('<div class="message message-valid">'.nl2br(Dict::S('UI:ErrorPage:KittyDisclaimer')).'</div>'); $this->add('<div class="message message-valid">'.nl2br(Dict::S('UI:ErrorPage:KittyDisclaimer')).'</div>');
} }
$this->log_error($sText); $this->log_error($sText);

View File

@@ -152,20 +152,20 @@ JS
parent::InitializeLinkedScripts(); parent::InitializeLinkedScripts();
// Used throughout the app. // Used throughout the app.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery/dist/jquery.min.js'); $this->LinkScriptFromAppRoot('node_modules/jquery/dist/jquery.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.blockUI.js'); $this->LinkScriptFromAppRoot('js/jquery.blockUI.js');
if (utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser if (utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
{ {
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev-params.js'); $this->LinkScriptFromAppRoot('js/jquery-migrate.dev-params.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev.js'); $this->LinkScriptFromAppRoot('js/jquery-migrate.dev.js');
} else { } else {
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.prod.min.js'); $this->LinkScriptFromAppRoot('js/jquery-migrate.prod.min.js');
} }
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery-ui-dist/jquery-ui.min.js'); $this->LinkScriptFromAppRoot('node_modules/jquery-ui-dist/jquery-ui.min.js');
// Used throughout the app. // Used throughout the app.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js'); $this->LinkScriptFromAppRoot('js/utils.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/latinise/latinise.min.js'); $this->LinkScriptFromAppRoot('js/latinise/latinise.min.js');
} }
/** /**
@@ -250,7 +250,7 @@ JS
// TODO 3.0.0: Remove light-grey when development of Full Moon is done. // TODO 3.0.0: Remove light-grey when development of Full Moon is done.
// TODO 3.0.0: Reuse theming mechanism for Full Moon // TODO 3.0.0: Reuse theming mechanism for Full Moon
$sCssThemeUrl = ThemeHandler::GetCurrentThemeUrl(); $sCssThemeUrl = ThemeHandler::GetCurrentThemeUrl();
$this->add_linked_stylesheet($sCssThemeUrl); $this->LinkStylesheetFromURI($sCssThemeUrl);
} }
protected function GetReadyScriptsStartedTrigger(): ?string protected function GetReadyScriptsStartedTrigger(): ?string

View File

@@ -77,18 +77,17 @@ class UnauthenticatedWebPage extends NiceWebPage
$this->SetContentType('text/html'); $this->SetContentType('text/html');
// - bootstrap // - bootstrap
$this->add_linked_script(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/js/bootstrap.min.js'); $this->LinkScriptFromURI(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/js/bootstrap.min.js');
// Note: Since 2.6.0 moment was moved from portal to iTop core // Note: Since 2.6.0 moment was moved from portal to iTop core
$sMomentURL = utils::GetAbsoluteUrlAppRoot().'/js/moment-with-locales.min.js'; $this->LinkScriptFromAppRoot('js/moment-with-locales.min.js');
$this->add_linked_script($sMomentURL);
$this->add_linked_script(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js'); $this->LinkScriptFromURI(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js');
// CSS files // CSS files
$this->add_linked_stylesheet(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/css/bootstrap.min.css'); $this->LinkStylesheetFromURI(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap/css/bootstrap.min.css');
$this->add_saas(UAWP_PORTAL_PUBLIC_FOLDER_RELATIVE_PATH . 'css/bootstrap-theme-combodo.scss'); $this->add_saas(UAWP_PORTAL_PUBLIC_FOLDER_RELATIVE_PATH . 'css/bootstrap-theme-combodo.scss');
$this->add_linked_stylesheet(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css'); $this->LinkStylesheetFromURI(UAWP_PORTAL_PUBLIC_FOLDER_ABSOLUTE_URL . 'lib/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css');
// Default theme // Default theme
$this->add_saas('css/unauthenticated.scss'); $this->add_saas('css/unauthenticated.scss');
@@ -279,13 +278,13 @@ class UnauthenticatedWebPage extends NiceWebPage
*/ */
protected function LoadTheme() protected function LoadTheme()
{ {
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
// Default theme // Default theme
$this->add_saas('css/unauthenticated.scss'); $this->add_saas('css/unauthenticated.scss');
// Custom theme to allow admin to override the default one. // Custom theme to allow admin to override the default one.
if(!empty($this->sCustomThemeUrl)) if(!empty($this->sCustomThemeUrl))
{ {
$this->add_linked_stylesheet($this->sCustomThemeUrl); $this->LinkStylesheetFromURI($this->sCustomThemeUrl);
} }
} }

View File

@@ -25,10 +25,13 @@ use DeprecatedCallsLog;
use Dict; use Dict;
use ExecutionKPI; use ExecutionKPI;
use IssueLog; use IssueLog;
use LogChannels;
use MetaModel; use MetaModel;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use UserRights; use UserRights;
use utils; use utils;
use const APPROOT;
use const MODULESROOT;
/** /**
@@ -73,6 +76,17 @@ class WebPage implements Page
*/ */
public const ENUM_SESSION_MESSAGE_SEVERITY_ERROR = 'error'; public const ENUM_SESSION_MESSAGE_SEVERITY_ERROR = 'error';
/**
* @var string
* @since 3.2.0
*/
protected const ENUM_RESOURCE_TYPE_JS = "js";
/**
* @var string
* @since 3.2.0
*/
protected const ENUM_RESOURCE_TYPE_CSS = "css";
/** /**
* @var string * @var string
* @since 3.0.0 * @since 3.0.0
@@ -512,6 +526,109 @@ class WebPage implements Page
return $oBlock; return $oBlock;
} }
/**
* Internal helper to link a resource from the iTop package (e.g. `<ITOP/`)
*
* @param string $sFileRelPath Rel. path from iTop app. root of the resource to link (e.g. `css/login.css`)
* @param string $sResourceType {@see static::ENUM_RESOURCE_TYPE_JS}, {@see static::ENUM_RESOURCE_TYPE_CSS}
*
* @return void
* @throws \Exception
* @internal
* @since 3.2.0 N°7315
*/
private function LinkResourceFromAppRoot(string $sFileRelPath, string $sResourceType): void
{
// Ensure there is actually a URI
if (utils::IsNullOrEmptyString(trim($sFileRelPath))) {
return;
}
if (false === utils::RealPath(APPROOT . $sFileRelPath, APPROOT)) {
IssueLog::Warning("Linked resource added to page with a path from outside app directory, it will be ignored.", LogChannels::CONSOLE, [
"linked_resource_uri" => $sFileRelPath,
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
]);
return;
}
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
// Ensure app root url ends with a slash as it is not guaranteed by the API
if (strcmp(substr($sFileRelPath, -1), '/') !== 0) {
$sAppRootUrl .= '/';
}
$this->LinkResourceFromURI($sAppRootUrl . $sFileRelPath, $sResourceType);
}
/**
* Internal helper to link a resource from any module
*
* @param string $sFileRelPath Rel. path from current environment (e.g. `<ITOP>/env-production/`) of the resource to link (e.g. `some-module/asset/css/some-file.css`)
* @param string $sResourceType {@see static::ENUM_RESOURCE_TYPE_JS}, {@see static::ENUM_RESOURCE_TYPE_CSS}
*
* @return void
* @throws \Exception
* @internal
* @since 3.2.0 N°7315
*/
private function LinkResourceFromModule(string $sFileRelPath, string $sResourceType): void
{
// Ensure there is actually a URI
if (utils::IsNullOrEmptyString(trim($sFileRelPath))) {
return;
}
if (false === utils::RealPath(MODULESROOT . $sFileRelPath, MODULESROOT)) {
IssueLog::Warning("Linked resource added to page with a path from outside current env. directory, it will be ignored.", LogChannels::CONSOLE, [
"linked_resource_url" => $sFileRelPath,
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
]);
return;
}
$this->LinkResourceFromURI(utils::GetAbsoluteUrlModulesRoot() . $sFileRelPath, $sResourceType);
}
/**
* Internal helper to link a resource from any URI, may it be on iTop server or an external one
*
* @param string $sFileAbsURI Abs. URI of the resource to link (e.g. `https://external.server.com/some-file.css`)
* @param string $sResourceType {@see static::ENUM_RESOURCE_TYPE_JS}, {@see static::ENUM_RESOURCE_TYPE_CSS}
*
* @return void
* @throws \Exception
* @internal
* @since 3.2.0 N°7315
*/
private function LinkResourceFromURI(string $sFileAbsURI, string $sResourceType): void
{
// Ensure there is actually a URI
if (utils::IsNullOrEmptyString(trim($sFileAbsURI))) {
return;
}
// Check if URI is absolute ("://" do allow any protocol), otherwise ignore the file
if (false === stripos($sFileAbsURI, "://")) {
IssueLog::Warning("Linked resource added to page with a non absolute URI, it will be ignored.", LogChannels::CONSOLE, [
"linked_resource_url" => $sFileAbsURI,
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
]);
return;
}
switch ($sResourceType) {
case static::ENUM_RESOURCE_TYPE_JS:
$this->a_linked_scripts[$sFileAbsURI] = $sFileAbsURI;
break;
case static::ENUM_RESOURCE_TYPE_CSS:
$this->a_linked_stylesheets[$sFileAbsURI] = $sFileAbsURI;
break;
}
}
/** /**
* Empty all base JS in the page's header * Empty all base JS in the page's header
* *
@@ -735,15 +852,77 @@ class WebPage implements Page
* Add a script (as an include, i.e. link) to the header of the page.<br> * Add a script (as an include, i.e. link) to the header of the page.<br>
* Handles duplicates : calling twice with the same script will add the script only once * Handles duplicates : calling twice with the same script will add the script only once
* *
* @uses WebPage::$a_linked_scripts * @param string $sLinkedScriptAbsUrl
* @param string $s_linked_script *
* @return void * @return void
* @uses WebPage::$a_linked_scripts
* @since 3.2.0 N°6935 $sLinkedScriptAbsUrl MUST be an absolute URL
* @deprecated 3.2.0 N°7315 Use {@see static::LinkScriptFromXXX()} instead
*/ */
public function add_linked_script($s_linked_script) public function add_linked_script($sLinkedScriptAbsUrl)
{ {
if (!empty(trim($s_linked_script))) { DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
$this->a_linked_scripts[$s_linked_script] = $s_linked_script;
// Ensure there is actually a URI
if (utils::IsNullOrEmptyString(trim($sLinkedScriptAbsUrl))) {
return;
} }
// Check if URI is absolute ("://" do allow any protocol), otherwise warn that it's a deprecated behavior
if (false === stripos($sLinkedScriptAbsUrl, "://")) {
IssueLog::Warning("Linked script added to page via deprecated API with a non absolute URL, it may lead to it not being loaded and causing javascript errors.", null, [
"linked_script_url" => $sLinkedScriptAbsUrl,
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
]);
}
$this->a_linked_scripts[$sLinkedScriptAbsUrl] = $sLinkedScriptAbsUrl;
}
/**
* Use to link JS files from the iTop package (e.g. `<ITOP>/js/*`)
*
* @param string $sFileRelPath Rel. path from iTop app. root of the JS file to link (e.g. `js/utils.js`)
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkScriptFromAppRoot(string $sFileRelPath): void
{
$this->LinkResourceFromAppRoot($sFileRelPath, static::ENUM_RESOURCE_TYPE_JS);
}
/**
* Use to link JS files from any module
*
* @param string $sFileRelPath Rel. path from current environment (e.g. `<ITOP>/env-production/`) of the JS file to link (e.g. `some-module/asset/js/some-file.js`)
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkScriptFromModule(string $sFileRelPath): void
{
$this->LinkResourceFromModule($sFileRelPath, static::ENUM_RESOURCE_TYPE_JS);
}
/**
* Use to link JS files from any URI, typically an external server
*
* @param string $sFileAbsURI Abs. URI of the JS file to link (e.g. `https://external.server.com/some-file.js`)
* Note: Any non-absolute URI will be ignored.
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkScriptFromURI(string $sFileAbsURI): void
{
$this->LinkResourceFromURI($sFileAbsURI, static::ENUM_RESOURCE_TYPE_JS);
} }
/** /**
@@ -925,13 +1104,76 @@ JS;
* Add a CSS stylesheet (as an include, i.e. link) to the header of the page * Add a CSS stylesheet (as an include, i.e. link) to the header of the page
* Handles duplicates since 3.0.0 : calling twig with the same stylesheet will add the stylesheet only once * Handles duplicates since 3.0.0 : calling twig with the same stylesheet will add the stylesheet only once
* *
* @param string $s_linked_stylesheet * @param string $sLinkedStylesheet
* @param string $s_condition * @param string $sCondition
* @return void * @return void
* @since 3.2.0 N°6935 $sLinkedStylesheet MUST be an absolute URL
* @deprecated 3.2.0 N°7315 Use {@see static::LinkStylesheetFromXXX()} instead
*/ */
public function add_linked_stylesheet($s_linked_stylesheet, $s_condition = "") public function add_linked_stylesheet($sLinkedStylesheet, $sCondition = "")
{ {
$this->a_linked_stylesheets[$s_linked_stylesheet] = array('link' => $s_linked_stylesheet, 'condition' => $s_condition); DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
// Ensure there is actually a URI
if (utils::IsNullOrEmptyString(trim($sLinkedStylesheet))) {
return;
}
// Check if URI is absolute ("://" do allow any protocol), otherwise warn that it's a deprecated behavior
if (false === stripos($sLinkedStylesheet, "://")) {
IssueLog::Warning("Linked stylesheet added to page via deprecated API with a non absolute URL, it may lead to it not being loaded and causing visual glitches.", null, [
"linked_stylesheet_url" => $sLinkedStylesheet,
"request_uri" => $_SERVER['REQUEST_URI'] ?? '' /* CLI */,
]);
}
$this->a_linked_stylesheets[$sLinkedStylesheet] = array('link' => $sLinkedStylesheet, 'condition' => $sCondition);
}
/**
* Use to link CSS files from the iTop package (e.g. `<ITOP>/css/*`)
*
* @param string $sFileRelPath Rel. path from iTop app. root of the CSS file to link (e.g. `css/login.css`)
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkStylesheetFromAppRoot(string $sFileRelPath): void
{
$this->LinkResourceFromAppRoot($sFileRelPath, static::ENUM_RESOURCE_TYPE_CSS);
}
/**
* Use to link CSS files from any module
*
* @param string $sFileRelPath Rel. path from current environment (e.g. `<ITOP>/env-production/`) of the CSS file to link (e.g. `some-module/asset/css/some-file.css`)
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkStylesheetFromModule(string $sFileRelPath): void
{
$this->LinkResourceFromModule($sFileRelPath, static::ENUM_RESOURCE_TYPE_CSS);
}
/**
* Use to link CSS files from any URI, typically an external server
*
* @param string $sFileAbsURI Abs. URI of the CSS file to link (e.g. `https://external.server.com/some-file.css`)
* Note: Any non-absolute URI will be ignored.
*
* @return void
* @throws \Exception
* @since 3.2.0 N°7315
* @api
*/
public function LinkStylesheetFromURI(string $sFileAbsURI): void
{
$this->LinkResourceFromURI($sFileAbsURI, static::ENUM_RESOURCE_TYPE_CSS);
} }
/** /**
@@ -1001,7 +1243,7 @@ JS;
$sRootUrl = '../'; $sRootUrl = '../';
} }
$sCSSUrl = $sRootUrl.$sCssRelPath; $sCSSUrl = $sRootUrl.$sCssRelPath;
$this->add_linked_stylesheet($sCSSUrl); $this->LinkStylesheetFromURI($sCSSUrl);
} }
/** /**

View File

@@ -172,49 +172,49 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
parent::InitializeLinkedScripts(); parent::InitializeLinkedScripts();
// Used by forms // Used by forms
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/leave_handler.js'); $this->LinkScriptFromAppRoot('js/leave_handler.js');
// Used by external keys, DM viewer // Used by external keys, DM viewer
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.treeview.min.js'); $this->LinkScriptFromAppRoot('js/jquery.treeview.min.js');
// Used by advanced search, date(time) attributes. Coupled to the PrepareWidgets() JS function. // Used by advanced search, date(time) attributes. Coupled to the PrepareWidgets() JS function.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-timepicker-addon.min.js'); $this->LinkScriptFromAppRoot('js/jquery-ui-timepicker-addon.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-timepicker-addon-i18n.min.js'); $this->LinkScriptFromAppRoot('js/jquery-ui-timepicker-addon-i18n.min.js');
// Used by external keys and other drop down lists // Used by external keys and other drop down lists
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js'); $this->LinkScriptFromAppRoot('js/selectize.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/selectize-plugin-a11y/selectize-plugin-a11y.js'); $this->LinkScriptFromAppRoot('node_modules/selectize-plugin-a11y/selectize-plugin-a11y.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.multiselect.js'); $this->LinkScriptFromAppRoot('js/jquery.multiselect.js');
// Used by inline image, CKEditor and other places // Used by inline image, CKEditor and other places
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/jquery.magnific-popup.min.js'); $this->LinkScriptFromAppRoot('node_modules/magnific-popup/dist/jquery.magnific-popup.min.js');
// Used by date(time) attibutes, activity panel, ... // Used by date(time) attibutes, activity panel, ...
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/moment-with-locales.min.js'); $this->LinkScriptFromAppRoot('js/moment-with-locales.min.js');
// Used by the newsroom // Used by the newsroom
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/showdown/dist/showdown.min.js'); $this->LinkScriptFromAppRoot('node_modules/showdown/dist/showdown.min.js');
// Tooltips // Tooltips
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/@popperjs/core/dist/umd/popper.min.js'); $this->LinkScriptFromAppRoot('node_modules/@popperjs/core/dist/umd/popper.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy-bundle.umd.min.js'); $this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.min.js');
// Toasts // Toasts
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/toastify-js/src/toastify.js'); $this->LinkScriptFromAppRoot('node_modules/toastify-js/src/toastify.js');
// Keyboard shortcuts // Keyboard shortcuts
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/mousetrap/mousetrap.min.js'); $this->LinkScriptFromAppRoot('node_modules/mousetrap/mousetrap.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/mousetrap/plugins/record/mousetrap-record.min.js'); $this->LinkScriptFromAppRoot('node_modules/mousetrap/plugins/record/mousetrap-record.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/keyboard-shortcuts.js'); $this->LinkScriptFromAppRoot('js/pages/backoffice/keyboard-shortcuts.js');
// Used throughout the app. // Used throughout the app.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/toolbox.js'); $this->LinkScriptFromAppRoot('js/pages/backoffice/toolbox.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/on-ready.js'); $this->LinkScriptFromAppRoot('js/pages/backoffice/on-ready.js');
// Used by dashboard editor // Used by dashboard editor
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/property_field.js'); $this->LinkScriptFromAppRoot('js/property_field.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/icon_select.js'); $this->LinkScriptFromAppRoot('js/icon_select.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/ajaxfileupload.js'); $this->LinkScriptFromAppRoot('js/ajaxfileupload.js');
} }
/** /**
@@ -257,24 +257,24 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
parent::InitializeLinkedStylesheets(); parent::InitializeLinkedStylesheets();
// Used by advanced search, date(time) attributes. Coupled to the PrepareWidgets() JS function. // Used by advanced search, date(time) attributes. Coupled to the PrepareWidgets() JS function.
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/jquery-ui-timepicker-addon.css'); $this->LinkStylesheetFromAppRoot('css/jquery-ui-timepicker-addon.css');
// Used by inline image, CKEditor and other places // Used by inline image, CKEditor and other places
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/magnific-popup.css'); $this->LinkStylesheetFromAppRoot('node_modules/magnific-popup/dist/magnific-popup.css');
// Tooltips // Tooltips
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy.css'); $this->LinkStylesheetFromAppRoot('node_modules/tippy.js/dist/tippy.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/animations/shift-away-subtle.css'); $this->LinkStylesheetFromAppRoot('node_modules/tippy.js/animations/shift-away-subtle.css');
// Icons // Icons
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css'); $this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
// Note: CKEditor files can't be moved easily as we need to find a way to init the "disabler" plugin, {@see js/toolbox.js} // Note: CKEditor files can't be moved easily as we need to find a way to init the "disabler" plugin, {@see js/toolbox.js}
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'js/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css'); $this->LinkStylesheetFromAppRoot('js/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css');
// Used by external keys and other drop down lists // Used by external keys and other drop down lists
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css'); $this->LinkStylesheetFromAppRoot('css/selectize.default.css');
} }
/** /**
@@ -871,7 +871,7 @@ HTML;
/** @var \iBackofficeLinkedScriptsExtension $oExtensionInstance */ /** @var \iBackofficeLinkedScriptsExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iBackofficeLinkedScriptsExtension') as $oExtensionInstance) { foreach (MetaModel::EnumPlugins('iBackofficeLinkedScriptsExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->GetLinkedScriptsAbsUrls() as $sScriptUrl) { foreach ($oExtensionInstance->GetLinkedScriptsAbsUrls() as $sScriptUrl) {
$this->add_linked_script($sScriptUrl); $this->LinkScriptFromURI($sScriptUrl);
} }
} }
// - API: Early inline scripts // - API: Early inline scripts
@@ -898,7 +898,7 @@ HTML;
/** @var \iBackofficeLinkedStylesheetsExtension $oExtensionInstance */ /** @var \iBackofficeLinkedStylesheetsExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iBackofficeLinkedStylesheetsExtension') as $oExtensionInstance) { foreach (MetaModel::EnumPlugins('iBackofficeLinkedStylesheetsExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->GetLinkedStylesheetsAbsUrls() as $sStylesheetUrl) { foreach ($oExtensionInstance->GetLinkedStylesheetsAbsUrls() as $sStylesheetUrl) {
$this->add_linked_stylesheet($sStylesheetUrl); $this->LinkStylesheetFromURI($sStylesheetUrl);
} }
} }
// - API: Inline style // - API: Inline style

View File

@@ -54,7 +54,7 @@ class iTopWizardWebPage extends iTopWebPage
$sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep'; $sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep';
$aSteps[] = "<div class=\"$sStyle\"><span>$sStepTitle</span></div>"; $aSteps[] = "<div class=\"$sStyle\"><span>$sStepTitle</span></div>";
} }
$sWizardHeader = "<div class=\"wizHeader\"><h1>".utils::EscapeHtml($this->s_title)."</h1>\n".implode("<div class=\"wizSeparator\"><img align=\"bottom\" src=\"../images/wizArrow.gif\"></div>", $aSteps)."<br style=\"clear:both;\"/></div>\n"; $sWizardHeader = "<div class=\"wizHeader\"><h1>".utils::EscapeHtml($this->s_title)."</h1>\n".implode("<div class=\"wizSeparator\"><img align=\"bottom\" src=\"" . utils::GetAbsoluteUrlAppRoot() . "images/wizArrow.gif\"></div>", $aSteps)."<br style=\"clear:both;\"/></div>\n";
$this->s_content = "$sWizardHeader<div class=\"wizContainer\">".$this->s_content."</div>"; $this->s_content = "$sWizardHeader<div class=\"wizContainer\">".$this->s_content."</div>";
parent::output(); parent::output();
} }

View File

@@ -845,7 +845,7 @@ EOF
); );
$sVersionString = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION); $sVersionString = Dict::Format('UI:iTopVersion:Short', ITOP_APPLICATION, ITOP_VERSION);
$oPage->add('<div id="about_box"><div class="ibo-about-box--top-part">'); $oPage->add('<div id="about_box"><div class="ibo-about-box--top-part">');
$oPage->add('<div><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="../images/logos/logo-combodo-dark.svg?t='.utils::GetCacheBusterTimestamp().'"/></a></div>'); $oPage->add('<div><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/logos/logo-combodo-dark.svg?t='.utils::GetCacheBusterTimestamp().'"/></a></div>');
$oPage->add('<div>'.$sVersionString.'</div>'); $oPage->add('<div>'.$sVersionString.'</div>');
$oPage->add("</div>"); $oPage->add("</div>");
self::DisplayAboutLicenses($oPage); self::DisplayAboutLicenses($oPage);
@@ -927,7 +927,7 @@ EOF
// Display // Display
// //
$oPage->add('<div id="about_box"><div class="ibo-about-box--top-part">'); $oPage->add('<div id="about_box"><div class="ibo-about-box--top-part">');
$oPage->add('<div><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="../images/logos/logo-combodo-dark.svg?t='.utils::GetCacheBusterTimestamp().'"/></a></div>'); $oPage->add('<div><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/logos/logo-combodo-dark.svg?t='.utils::GetCacheBusterTimestamp().'"/></a></div>');
$oPage->add('<div>'.$sVersionString.'<br/>'.'MySQL: '.$sMySQLVersion.'<br/>'.'PHP: '.$sPHPVersion.'<br/></div>'); $oPage->add('<div>'.$sVersionString.'<br/>'.'MySQL: '.$sMySQLVersion.'<br/>'.'PHP: '.$sPHPVersion.'<br/></div>');
$oPage->add("</div>"); $oPage->add("</div>");

View File

@@ -315,7 +315,7 @@ JS;
} }
// - JS files // - JS files
foreach (static::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) { foreach (static::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sJsFileRelPath); $oPage->LinkScriptFromAppRoot($sJsFileRelPath);
} }
// Note: Code duplicated to the case 'apply_modify' in UI.php when a data integrity issue has been found // Note: Code duplicated to the case 'apply_modify' in UI.php when a data integrity issue has been found
@@ -771,7 +771,7 @@ JS;
protected function AddRequiredForModificationJsFilesToPage(iTopWebPage &$oPage): void protected function AddRequiredForModificationJsFilesToPage(iTopWebPage &$oPage): void
{ {
foreach (static::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) { foreach (static::EnumRequiredForModificationJsFilesRelPaths() as $sJsFileRelPath) {
$oPage->add_linked_script("../$sJsFileRelPath"); $oPage->LinkScriptFromAppRoot($sJsFileRelPath);
} }
} }

View File

@@ -56,7 +56,7 @@ class iTopNewsroomController extends Controller
public function OperationViewAll() public function OperationViewAll()
{ {
$oPage = new iTopWebPage(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Title')); $oPage = new iTopWebPage(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Title'));
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/itop-newsroom.view-all.js'); $oPage->LinkScriptFromAppRoot('js/pages/backoffice/itop-newsroom.view-all.js');
// Add title block // Add title block
// Make bulk actions block // Make bulk actions block
$oBulkActionsBlock = PanelUIBlockFactory::MakeForInformation(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Title')); $oBulkActionsBlock = PanelUIBlockFactory::MakeForInformation(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Title'));
@@ -233,10 +233,6 @@ $.ajax({
type: 'POST', type: 'POST',
success: function(data) { success: function(data) {
if (data.status === 'success') { if (data.status === 'success') {
let MarkAsReadButton = oNotificationToMarkAsRead.find('.ibo-button-group:not(.ibo-is-hidden)');
let MarkAsUnreadButton = oNotificationToMarkAsRead.find('.ibo-button-group.ibo-is-hidden');
MarkAsReadButton.addClass('ibo-is-hidden');
MarkAsUnreadButton.removeClass('ibo-is-hidden');
oNotificationToMarkAsRead.removeClass('ibo-notifications--view-all--item--unread').addClass('ibo-notifications--view-all--item--read'); oNotificationToMarkAsRead.removeClass('ibo-notifications--view-all--item--unread').addClass('ibo-notifications--view-all--item--read');
CombodoToast.OpenSuccessToast(data.message); CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.read'); $('.ibo-notifications--view-all--container').trigger('itop.notification.read');
@@ -273,12 +269,6 @@ $.ajax({
type: 'POST', type: 'POST',
success: function(data) { success: function(data) {
if (data.status === 'success') { if (data.status === 'success') {
let MarkAsUnreadButton = oNotificationToMarkAsUnread.find('.ibo-button-group:not(.ibo-is-hidden)');
let MarkAsReadButton = oNotificationToMarkAsUnread.find('.ibo-button-group.ibo-is-hidden');
MarkAsReadButton.removeClass('ibo-is-hidden');
MarkAsUnreadButton.addClass('ibo-is-hidden');
oNotificationToMarkAsUnread.removeClass('ibo-notifications--view-all--item--read').addClass('ibo-notifications--view-all--item--unread'); oNotificationToMarkAsUnread.removeClass('ibo-notifications--view-all--item--read').addClass('ibo-notifications--view-all--item--unread');
CombodoToast.OpenSuccessToast(data.message); CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.unread'); $('.ibo-notifications--view-all--container').trigger('itop.notification.unread');
@@ -384,15 +374,15 @@ JS
$oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER,true); $oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER,true);
} }
// Prepare Event actions
$oMarkAsReadPopoverMenu = new PopoverMenu();
$oMarkAsUnreadPopoverMenu = new PopoverMenu();
// Common actions // Common actions
$sDeleteUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.delete_event', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]); $sDeleteUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.delete_event', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]);
$oDeleteButton = new JSPopupMenuItem( $oDeleteButton = ButtonUIBlockFactory::MakeForAlternativeDestructiveAction(
'',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label', 'UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label',
Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'), 'UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'
);
$oDeleteButton->SetOnClickJsCode(
<<<JS <<<JS
let oSelf = this; let oSelf = this;
@@ -410,31 +400,26 @@ $.ajax({
} }
} }
}); });
JS, JS
'_blank' )
); ->SetIconClass('fas fa-trash-alt')
$oViewButton = new URLPopupMenuItem( ->SetTooltip(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'));
'UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label',
$oViewButton = ButtonUIBlockFactory::MakeIconLink('fas fa-external-link-alt',
Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label'), Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label'),
Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.view_event', ['event_id' => $oEvent->GetKey()]), Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.view_event', ['event_id' => $iEventId]),
'_blank' '_blank'
); );
// Mark as read action // Mark as read action
$oMarkAsReadButton = ButtonUIBlockFactory::MakeForAlternativeSecondaryAction( $oMarkAsReadButton = ButtonUIBlockFactory::MakeForAlternativeSecondaryAction(
Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label'), '',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label', 'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label'
); );
$oMarkAsReadButton->AddCSSClass('ibo-notifications--view-all--read-action')
// Mark as read action ->SetIconClass('far fa-envelope-open')
$oMarkAsReadPopoverMenu->AddItem('more-actions', PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oViewButton))->SetContainer(PopoverMenu::ENUM_CONTAINER_PARENT); ->SetTooltip(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label'));
$oMarkAsReadPopoverMenu->AddItem('more-actions', PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oDeleteButton))->SetContainer(PopoverMenu::ENUM_CONTAINER_PARENT);
// Mark as unread action
$oMarkAsUnreadPopoverMenu->AddItem('more-actions', PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oViewButton))->SetContainer(PopoverMenu::ENUM_CONTAINER_PARENT);
$oMarkAsUnreadPopoverMenu->AddItem('more-actions', PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oDeleteButton))->SetContainer(PopoverMenu::ENUM_CONTAINER_PARENT);
// Mark as unread action // Mark as unread action
$sMarkAsReadUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.mark_as_read', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]); $sMarkAsReadUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.mark_as_read', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]);
@@ -446,8 +431,6 @@ JS,
type: 'POST', type: 'POST',
success: function(data) { success: function(data) {
if (data.status === 'success') { if (data.status === 'success') {
$(oSelf).parent('.ibo-button-group').addClass('ibo-is-hidden');
$(oSelf).parent('.ibo-button-group').siblings('.ibo-button-group').removeClass('ibo-is-hidden');
$(oSelf).parents('.ibo-object-summary').removeClass('ibo-notifications--view-all--item--unread').addClass('ibo-notifications--view-all--item--read'); $(oSelf).parents('.ibo-object-summary').removeClass('ibo-notifications--view-all--item--unread').addClass('ibo-notifications--view-all--item--read');
CombodoToast.OpenSuccessToast(data.message); CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.read'); $('.ibo-notifications--view-all--container').trigger('itop.notification.read');
@@ -460,13 +443,14 @@ JS,
JS JS
); );
$oMarkAsReadButtonGroup = ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu($oMarkAsReadButton, $oMarkAsReadPopoverMenu);
$oMarkAsUnreadButton = ButtonUIBlockFactory::MakeForAlternativeSecondaryAction( $oMarkAsUnreadButton = ButtonUIBlockFactory::MakeForAlternativeSecondaryAction(
Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label'), '',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label', 'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label',
'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label' 'UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label'
); );
$oMarkAsUnreadButton->AddCSSClass('ibo-notifications--view-all--unread-action')
->SetIconClass('far fa-envelope')
->SetTooltip(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsUnread:Label'));
$sMarkAsUnreadUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.mark_as_unread', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]); $sMarkAsUnreadUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.mark_as_unread', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]);
$oMarkAsUnreadButton->SetOnClickJsCode( $oMarkAsUnreadButton->SetOnClickJsCode(
<<<JS <<<JS
@@ -476,8 +460,6 @@ JS
type: 'POST', type: 'POST',
success: function(data) { success: function(data) {
if (data.status === 'success') { if (data.status === 'success') {
$(oSelf).parent('.ibo-button-group').addClass('ibo-is-hidden');
$(oSelf).parent('.ibo-button-group').siblings('.ibo-button-group').removeClass('ibo-is-hidden');
$(oSelf).parents('.ibo-object-summary').removeClass('ibo-notifications--view-all--item--read').addClass('ibo-notifications--view-all--item--unread'); $(oSelf).parents('.ibo-object-summary').removeClass('ibo-notifications--view-all--item--read').addClass('ibo-notifications--view-all--item--unread');
CombodoToast.OpenSuccessToast(data.message); CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.unread'); $('.ibo-notifications--view-all--container').trigger('itop.notification.unread');
@@ -490,24 +472,17 @@ JS
JS JS
); );
$oMarkAsUnreadButtonGroup = ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu($oMarkAsUnreadButton, $oMarkAsUnreadPopoverMenu);
// Add actions to the object summary block and remove old button // Add actions to the object summary block and remove old button
$oOldButtonId = $oEventBlock->GetActions()->GetId(); $oOldButtonId = $oEventBlock->GetActions()->GetId();
$oEventBlock->RemoveSubBlock($oOldButtonId); $oEventBlock->RemoveSubBlock($oOldButtonId);
$oEventBlock->SetToolBlocks([$oMarkAsReadButtonGroup, $oMarkAsUnreadButtonGroup]); $oEventBlock->SetToolBlocks([$oMarkAsUnreadButton, $oMarkAsReadButton, $oViewButton, $oDeleteButton]);
$oActionsBlock = new UIContentBlock(); $oActionsBlock = new UIContentBlock();
$oActionsBlock->AddSubBlock($oMarkAsReadButtonGroup); $oActionsBlock->AddSubBlock($oMarkAsUnreadButton);
$oActionsBlock->AddSubBlock($oMarkAsUnreadButtonGroup); $oActionsBlock->AddSubBlock($oMarkAsReadButton);
$oActionsBlock->AddSubBlock($oViewButton);
$oActionsBlock->AddSubBlock($oDeleteButton);
$oEventBlock->SetActions($oActionsBlock); $oEventBlock->SetActions($oActionsBlock);
// Display the right button depending on the read status
if($oEvent->Get('read') === 'no'){
$oMarkAsUnreadButtonGroup->SetCSSClasses(['ibo-is-hidden']);
}
else{
$oMarkAsReadButtonGroup->SetCSSClasses(['ibo-is-hidden']);
}
$oMainContentBlock->AddSubBlock($oEventBlock); $oMainContentBlock->AddSubBlock($oEventBlock);
} }

View File

@@ -255,7 +255,7 @@ JS
// Add Set JS files to the page as we used a renderer ourselves, they are not added automatically by the page // Add Set JS files to the page as we used a renderer ourselves, they are not added automatically by the page
foreach (Set::DEFAULT_JS_FILES_REL_PATH as $sJsFile) { foreach (Set::DEFAULT_JS_FILES_REL_PATH as $sJsFile) {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sJsFile); $oPage->LinkScriptFromAppRoot($sJsFile);
} }
$oPage->AddSubBlock($oNotificationsPanel); $oPage->AddSubBlock($oNotificationsPanel);

View File

@@ -80,11 +80,11 @@ class ConsoleBlockRenderer extends BlockRenderer
{ {
// CSS files // CSS files
foreach ($oBlock->GetCssFilesUrlRecursively(true) as $sFileAbsUrl) { foreach ($oBlock->GetCssFilesUrlRecursively(true) as $sFileAbsUrl) {
$oPage->add_linked_stylesheet($sFileAbsUrl); $oPage->LinkStylesheetFromURI($sFileAbsUrl);
} }
// JS files // JS files
foreach ($oBlock->GetJsFilesUrlRecursively(true) as $sFileAbsUrl) { foreach ($oBlock->GetJsFilesUrlRecursively(true) as $sFileAbsUrl) {
$oPage->add_linked_script($sFileAbsUrl); $oPage->LinkScriptFromURI($sFileAbsUrl);
} }
static::AddCssJsTemplatesToPageRecursively($oPage, $oBlock, $aContextParams); static::AddCssJsTemplatesToPageRecursively($oPage, $oBlock, $aContextParams);
} }

View File

@@ -3,7 +3,7 @@
{% apply spaceless %} {% apply spaceless %}
<div style="height:250px;width:100%" class="dashboard_chart" id="my_chart_{{ oUIBlock.sChartId }}{{ oUIBlock.iChartCounter }}"> <div style="height:250px;width:100%" class="dashboard_chart" id="my_chart_{{ oUIBlock.sChartId }}{{ oUIBlock.iChartCounter }}">
<div style="height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%"> <div style="height:200px;line-height:200px;vertical-align:center;text-align:center;width:100%">
<img src="../images/indicator.gif"> <img src="{{ get_absolute_url_app_root() }}images/indicator.gif">
</div> </div>
</div> </div>
{% endapply %} {% endapply %}

View File

@@ -0,0 +1,20 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Application\WebPage;
use Combodo\iTop\Application\WebPage\WebPage;
class WebPageMock extends WebPage
{
public function __construct()
{
// Don't call parent construct as we don't want the ob_start() method to be called (it would mess with PHPUnit)
}
}

View File

@@ -0,0 +1,202 @@
<?php
/*
* @copyright Copyright (C) 2010-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Application\WebPage;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
/**
* @covers \Combodo\iTop\Application\WebPage\WebPage
*/
class WebPageTest extends ItopDataTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->RequireOnceUnitTestFile("./WebPageMock.php");
}
/**
* @dataProvider LinkScriptMethodsProvider
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkScriptFromAppRoot()
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkScriptFromModule()
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkScriptFromURI()
*
* @param string $sMethodName
* @param string $sInputURI
* @param int $iExpectedCount
*
* @return void
* @throws \ReflectionException
*/
public function testLinkScriptMethods(string $sMethodName, string $sInputURI, int $iExpectedCount): void
{
$oPage = new WebPageMock('');
$this->InvokeNonPublicMethod(WebPage::class, "EmptyLinkedScripts", $oPage);
$this->InvokeNonPublicMethod(WebPage::class, $sMethodName, $oPage, [$sInputURI]);
$aLinkedScripts = $this->GetNonPublicProperty($oPage, "a_linked_scripts");
$this->assertEquals($iExpectedCount, count($aLinkedScripts), "Linked scripts count should be $iExpectedCount");
}
public function LinkScriptMethodsProvider(): array
{
return [
// LinkScriptFromAppRoot
"LinkScriptFromAppRoot: Empty URI should be ignored" => [
"LinkScriptFromAppRoot",
"",
0,
],
"LinkScriptFromAppRoot: Relative URI of existing file should be completed / added" => [
"LinkScriptFromAppRoot",
"js/utils.js",
1,
],
"LinkScriptFromAppRoot: Relative URI of NON existing file should be ignored" => [
"LinkScriptFromAppRoot",
"js/some-file.js",
0,
],
"LinkScriptFromAppRoot: Absolute URI should be ignored" => [
"LinkScriptFromAppRoot",
"https://external.server/file.js",
0,
],
// LinkScriptFromModule
"LinkScriptFromModule: Empty URI should be ignored" => [
"LinkScriptFromModule",
"",
0,
],
"LinkScriptFromModule: Relative URI of existing file should be completed / added" => [
"LinkScriptFromModule",
"itop-portal-base/portal/public/js/toolbox.js",
1,
],
"LinkScriptFromModule: Relative URI of NON existing file should be completed / added" => [
"LinkScriptFromModule",
"some-module/asset/js/some-file.js",
0,
],
"LinkScriptFromModule: Absolute URI should be ignored" => [
"LinkScriptFromModule",
"https://external.server/file.js",
0,
],
// LinkScriptFromURI
"LinkScriptFromURI: Empty URI should be ignored" => [
"LinkScriptFromURI",
"",
0,
],
"LinkScriptFromURI: Relative URI should be ignored" => [
"LinkScriptFromURI",
"js/utils.js",
0,
],
"LinkScriptFromURI: Absolute URI should be added" => [
"LinkScriptFromURI",
"https://external.server/file.js",
1,
],
];
}
/**
* @dataProvider LinkStylesheetMethodsProvider
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkStylesheetFromAppRoot()
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkStylesheetFromModule()
* @covers \Combodo\iTop\Application\WebPage\WebPage::LinkStylesheetFromURI()
*
* @param string $sMethodName
* @param string $sInputURI
* @param int $iExpectedCount
*
* @return void
* @throws \ReflectionException
*/
public function testLinkStylesheetMethods(string $sMethodName, string $sInputURI, int $iExpectedCount): void
{
$oPage = new WebPageMock('');
$this->InvokeNonPublicMethod(WebPage::class, "EmptyLinkedStylesheets", $oPage);
$this->InvokeNonPublicMethod(WebPage::class, $sMethodName, $oPage, [$sInputURI]);
$aLinkedStylesheets = $this->GetNonPublicProperty($oPage, "a_linked_stylesheets");
$this->assertEquals($iExpectedCount, count($aLinkedStylesheets), "Linked stylesheets count should be $iExpectedCount");
}
public function LinkStylesheetMethodsProvider(): array
{
return [
// LinkStylesheetFromAppRoot
"LinkStylesheetFromAppRoot: Empty URI should be ignored" => [
"LinkStylesheetFromAppRoot",
"",
0,
],
"LinkStylesheetFromAppRoot: Relative URI of existing file should be completed / added" => [
"LinkStylesheetFromAppRoot",
"css/login.css",
1,
],
"LinkStylesheetFromAppRoot: Relative URI of NON existing file should be ignored" => [
"LinkStylesheetFromAppRoot",
"css/some-file.css",
0,
],
"LinkStylesheetFromAppRoot: Absolute URI should be ignored" => [
"LinkStylesheetFromAppRoot",
"https://external.server/file.css",
0,
],
// LinkStylesheetFromModule
"LinkStylesheetFromModule: Empty URI should be ignored" => [
"LinkStylesheetFromModule",
"",
0,
],
"LinkStylesheetFromModule: Relative URI of existing file should be completed / added" => [
"LinkStylesheetFromModule",
"itop-portal-base/portal/public/css/portal.css",
1,
],
"LinkStylesheetFromModule: Relative URI of NON existing file should be completed / added" => [
"LinkStylesheetFromModule",
"some-module/asset/js/some-file.js",
0,
],
"LinkStylesheetFromModule: Absolute URI should be ignored" => [
"LinkStylesheetFromModule",
"https://external.server/file.js",
0,
],
// LinkStylesheetFromURI
"LinkStylesheetFromURI: Empty URI should be ignored" => [
"LinkStylesheetFromURI",
"",
0,
],
"LinkStylesheetFromURI: Relative URI should be ignored" => [
"LinkStylesheetFromURI",
"js/login.css",
0,
],
"LinkStylesheetFromURI: Absolute URI should be added" => [
"LinkStylesheetFromURI",
"https://external.server/file.css",
1,
],
];
}
}

View File

@@ -235,9 +235,9 @@ function FormatDatesInPreview(sRadioSelector, sPreviewSelector)
} }
EOF EOF
); );
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/tabularfieldsselector.js'); $oP->LinkScriptFromAppRoot('js/tabularfieldsselector.js');
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.dragtable.js'); $oP->LinkScriptFromAppRoot('js/jquery.dragtable.js');
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/dragtable.css'); $oP->LinkStylesheetFromAppRoot('css/dragtable.css');
$oForm = FormUIBlockFactory::MakeStandard("export-form"); $oForm = FormUIBlockFactory::MakeStandard("export-form");
$oForm->SetAction($sAction); $oForm->SetAction($sAction);
@@ -707,8 +707,8 @@ try
$oP = new NiceWebPage('iTop export'); $oP = new NiceWebPage('iTop export');
$oP->add_http_headers(); $oP->add_http_headers();
$oP->add_ready_script("$('table.listResults').tablesorter({widgets: ['MyZebra']});"); $oP->add_ready_script("$('table.listResults').tablesorter({widgets: ['MyZebra']});");
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $oP->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css'); $oP->LinkStylesheetFromAppRoot('css/font-awesome/css/v4-shims.min.css');
} else { } else {
$oP = new WebPage('iTop export'); $oP = new WebPage('iTop export');
$oP->add_http_headers(); $oP->add_http_headers();

View File

@@ -219,8 +219,8 @@ if (!empty($sExpression))
case 'html': case 'html':
$oP = new NiceWebPage("iTop - Export"); $oP = new NiceWebPage("iTop - Export");
$oP->add_style('body { overflow: auto; }'); // Show scroll bars if needed $oP->add_style('body { overflow: auto; }'); // Show scroll bars if needed
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $oP->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css'); $oP->LinkStylesheetFromAppRoot('css/font-awesome/css/v4-shims.min.css');
// Integration within MS-Excel web queries + HTTPS + IIS: // Integration within MS-Excel web queries + HTTPS + IIS:
// MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS // MS-IIS set these header values with no-cache... while Excel fails to do the job if using HTTPS