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;
$aEventsList[] = 'validate';
$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
$sDefaultUrl = $oAttDef->Get('default_image');
if (is_object($oDocument) && !$oDocument->IsEmpty()) {
@@ -2545,11 +2545,11 @@ HTML;
$sHTMLValue .= '</div></div>';
$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";
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/console_form_handler.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_set.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_field.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/subform_field.js');
$oPage->LinkScriptFromAppRoot('js/form_handler.js');
$oPage->LinkScriptFromAppRoot('js/console_form_handler.js');
$oPage->LinkScriptFromAppRoot('js/field_set.js');
$oPage->LinkScriptFromAppRoot('js/form_field.js');
$oPage->LinkScriptFromAppRoot('js/subform_field.js');
$oPage->add_ready_script(
<<<JS
$('#{$iId}_field_set').field_set($sFieldSetOptions);
@@ -2575,9 +2575,9 @@ JS
case 'Set':
case 'TagSet':
$sInputType = self::ENUM_INPUT_TYPE_TAGSET;
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js');
$oPage->LinkScriptFromAppRoot('js/selectize.min.js');
$oPage->LinkStylesheetFromAppRoot('css/selectize.default.css');
$oPage->LinkScriptFromAppRoot('js/jquery.itop-set-widget.js');
$oPage->add_dict_entry('Core:AttributeSet:placeholder');
@@ -3452,7 +3452,7 @@ EOF
// Dummy collapsible section created in order to get JS files
$oCollapsibleSection = new CollapsibleSection('');
foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) {
$oPage->add_linked_script($sJSFile);
$oPage->LinkScriptFromURI($sJSFile);
}
}
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);

View File

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

View File

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

View File

@@ -570,7 +570,7 @@ class DisplayBlock
} else {
// render it as an Ajax (asynchronous) call
$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('
$.post("ajax.render.php?style='.$this->m_sStyle.'",
{ operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },

View File

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

View File

@@ -232,12 +232,13 @@ class DisplayTemplate
static public function UnitTest()
{
require_once(APPROOT.'/application/startup.inc.php');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sTemplate = '<div class="page_header">
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
<h1>$class$: <span class="hilite">$name$</span></h1>
</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>
<itoptab name="Interfaces">
<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)
{
$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 = '';
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 = '')
{
$sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
@@ -368,7 +368,7 @@ JS
*/
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);
$bExtensions = true;
@@ -477,8 +477,8 @@ JS
$this->bSearchMode = $bSearchMode;
}
$sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;

View File

@@ -1446,7 +1446,7 @@ EOF
<<<EOF
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)
{
$('#$sAjaxDivId').html(data);

View File

@@ -397,6 +397,34 @@
</field>
</fields>
<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>
<items>
<item id="date">

View File

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

View File

@@ -217,7 +217,7 @@ class ormStopWatch
}
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);

View File

@@ -21,6 +21,9 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
grid-gap: $ibo-notifications--view-all--container--grid-gap;
.ibo-object-summary .ibo-panel--title{
font-size: $ibo-font-size-250;
}
.ibo-object-summary .ibo-panel--toolbar{
min-width: 102px;
}
.ibo-object-summary > .ibo-panel--body{
box-shadow: none;
@@ -53,7 +56,18 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
.ibo-notifications--view-all--item--unread .ibo-panel--body::before{
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 {
@extend %ibo-fully-centered-content;
flex-direction: column;

View File

@@ -185,6 +185,7 @@ abstract class AbstractAttachmentsRenderer
{
$sClass = $this->sObjClass;
$sId = $this->iObjKey;
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$iMaxUploadInBytes = AttachmentPlugIn::GetMaxUploadSize();
$sMaxUploadLabel = AttachmentPlugIn::GetMaxUpload();
$sFileTooBigLabel = Dict::Format('Attachments:Error:FileTooLarge', $sMaxUploadLabel);
@@ -195,15 +196,15 @@ abstract class AbstractAttachmentsRenderer
$oAddButton = FileSelectUIBlockFactory::MakeStandard('file', 'file');
$oAddButton->SetShowFilename(false);
$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 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(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->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/blueimp-file-upload/js/jquery.fileupload.js');
$this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
$this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
$this->oPage->add_ready_script(
<<<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>');
});
});
$('.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 );
JS
);

View File

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

View File

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

View File

@@ -57,7 +57,7 @@ function DisplayStatus(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>');
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
$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());
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>');
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
$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_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>');
@@ -263,8 +263,8 @@ try {
}
$oPage = new SetupPage(''); // Title will be set later, depending on $sOperation
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js');
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css');
$oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
$oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$oPage->add_style(<<<CSS
div.choice { margin: 0.5em;}

View File

@@ -305,9 +305,9 @@ try {
$sCloseUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/black-close.svg';
$oPage = new HubConnectorPage(Dict::S('iTopHub:Connect'));
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js');
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css');
$oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
$oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
$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:ConfigurationLink' => 'Configuration',
'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: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);
localStorage.removeItem(sKey);
}
CombodoToast.OpenSuccessToast(Dict.S('UI:Newsroom:ResetCache:Success:Message'));
},
_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--delete-action').attr('disabled', 'disabled');
}
$('#ibo-navigation-menu--notifications-menu').newsroom_menu("clearCache");
});
let fReadUnreadDisabled = function() {
@@ -28,6 +30,8 @@ let fReadUnreadDisabled = function() {
$('.ibo-notifications--view-all--read-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);

View File

@@ -350,7 +350,7 @@ try
case '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) {
$oP->add_linked_script("../$sJsFileRelPath");
$oP->LinkScriptFromAppRoot($sJsFileRelPath);
}
break;
}
@@ -651,7 +651,7 @@ try
$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 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 id=\"full_text_results\">\n");
$oP->add("<div id=\"full_text_progress_placeholder\" style=\"padding: 1.5em;\">&nbsp;</div>\n");
@@ -703,7 +703,7 @@ try
break;
///////////////////////////////////////////////////////////////////////////////////////////
/** @deprecated 3.1.0 Use the "object.new" route instead */
// Kept for backward compatibility
case 'new': // Form to create a new object

View File

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

View File

@@ -1375,7 +1375,7 @@ JS
<<<EOF
$('.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'};
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) {
$('.search-class-$sClassName').html(data);
@@ -1532,6 +1532,7 @@ EOF
case 'xlsx_export_dialog':
DeprecatedCallsLog::NotifyDeprecatedPhpEndpoint('Use "export_*" operations instead of "'.$operation.'"');
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$oPage->SetContentType('text/html');
$oPage->add(
<<<EOF
@@ -1561,11 +1562,11 @@ EOF
padding-left: 16px;
cursor: pointer;
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 {
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 {
@@ -1594,7 +1595,7 @@ EOF
);
$sJSLabels = json_encode($aLabels);
$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'});");
break;
@@ -2206,9 +2207,10 @@ EOF
case 'cke_browse':
$oPage = new NiceWebPage(Dict::S('UI:BrowseInlineImages'));
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/magnific-popup.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/magnific-popup/dist/jquery.magnific-popup.min.js');
$sImgUrl = utils::GetAbsoluteUrlAppRoot().INLINEIMAGE_DOWNLOAD_URL;
$oPage->LinkStylesheetFromAppRoot('node_modules/magnific-popup/dist/magnific-popup.css');
$oPage->LinkScriptFromAppRoot('node_modules/magnific-popup/dist/jquery.magnific-popup.min.js');
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
$sImgUrl = $sAppRootUrl.INLINEIMAGE_DOWNLOAD_URL;
/** @noinspection SuspiciousAssignmentsInspection cke_upload_and_browse and cke_browse are chained */
$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(
<<<EOF
@@ -2304,7 +2306,7 @@ EOF
$oPage->add_ready_script(
<<<EOF
$('#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();
$(this).prop('disabled', true);
});

View File

@@ -281,7 +281,7 @@ try
$oAllCategoriesDashlet
->AddCSSClasses(['ibo-dashlet--is-inline', 'ibo-dashlet-badge'])
->AddSubBlock(DashletFactory::MakeForDashletBadge(
'../images/icons/icons8-audit.svg',
utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-audit.svg',
utils::GetAbsoluteUrlAppRoot()."pages/audit.php?operation=audit",
$iCategoryCount,
Dict::S('UI:Audit:Interactive:Selection:BadgeAll')
@@ -304,7 +304,7 @@ try
/** @var AuditDomain $oAuditDomain */
while($oAuditDomain = $oDomainSet->Fetch()) {
$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 */
$oImage = $oAuditDomain->Get('icon');
if (!$oImage->IsEmpty()) {
@@ -357,9 +357,9 @@ try
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage($sTitle));
$oP->AddUiBlock(new Text($sSubTitle));
$oTotalBlock = DashletFactory::MakeForDashletBadge('../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'));
$oWorkingBlock = DashletFactory::MakeForDashletBadge('../images/icons/icons8-checkmark.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsValidated'));
$oTotalBlock = DashletFactory::MakeForDashletBadge(utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-audit.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsAudited'));
$oErrorBlock = DashletFactory::MakeForDashletBadge(utils::GetAbsoluteUrlAppRoot().'images/icons/icons8-delete.svg', '#', 0, Dict::S('UI:Audit:Dashboard:ObjectsInError'));
$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'];
@@ -436,7 +436,7 @@ try
foreach ($aErrors as $aErrorRow) {
$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['class'] = $oAuditCategory->GetReportColor($iCount, $iErrorsCount);
}

View File

@@ -400,6 +400,7 @@ try {
$iUnchanged = 0;
$aTableData = [];
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
foreach ($aRes as $iLine => $aResRow) {
$aTableRow = [];
@@ -414,7 +415,7 @@ try {
$sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$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';
break;
@@ -423,7 +424,7 @@ try {
$sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$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';
break;
@@ -432,7 +433,7 @@ try {
$sFinalClass = $aResRow['finalclass'];
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
$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';
if ($bSimulate) {
$sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate');
@@ -443,7 +444,7 @@ try {
case 'RowStatus_NewObj':
$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';
if ($bSimulate) {
$sMessage = Dict::S('UI:CSVReport-Object-ToCreate');
@@ -585,21 +586,21 @@ HTML;
$oMulticolumn->AddCSSClass('ml-1');
$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->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged));
$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->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');
$oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oCheckBoxUnchanged));
$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->SetBeforeInput(false);
$oCheckBoxUnchanged->GetInput()->AddCSSClass('ibo-input-checkbox');

View File

@@ -133,7 +133,7 @@ function ValidateOtherSettings()
}
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);
return false;
}
@@ -315,7 +315,11 @@ JS
// - Reset button
$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);
// - Cancel button
$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');
$sUserPicturesFolder = '../images/user-pictures/';
$sUserPicturesFolder = utils::GetAbsoluteUrlAppRoot() . 'images/user-pictures/';
$sUserDefaultPicture = appUserPreferences::GetPref('user_picture_placeholder', 'default-placeholder.png');
$sUserPicturePlaceHolderHtml = '';
$sUserPicturePlaceHolderHtml .= '<p>'.Dict::S('UI:Preferences:ChooseAPlaceholder+').'</p> <div class="ibo-preferences--user-preferences--picture-placeholder">';
@@ -916,7 +920,12 @@ try {
}
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);
break;

View File

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

View File

@@ -39,14 +39,14 @@ class SetupPage extends NiceWebPage
public function __construct($sTitle)
{
parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js");
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/@popperjs/core/dist/umd/popper.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy-bundle.umd.js');
$this->add_linked_script("../setup/setup.js");
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/dist/tippy.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/tippy.js/animations/shift-away-subtle.css');
$this->LinkScriptFromAppRoot("js/jquery.blockUI.js");
$this->LinkScriptFromAppRoot('node_modules/@popperjs/core/dist/umd/popper.js');
$this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.js');
$this->LinkScriptFromAppRoot("setup/setup.js");
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$this->LinkStylesheetFromAppRoot('node_modules/tippy.js/dist/tippy.css');
$this->LinkStylesheetFromAppRoot('node_modules/tippy.js/animations/shift-away-subtle.css');
$this->LoadTheme();
$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 CanMoveBackward()\n{\n".$oStep->JSCanMoveBackward()."\n}\n");
$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('<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('</div>'); // progress_content
$oPage->add('</fieldset>');

View File

@@ -55,7 +55,6 @@ class FormHelper
*/
public static function DisableAttributeBlobInputs(string $sClassName, array &$aExtraParams): void
{
// Initialize extra params array
if (!array_key_exists('fieldsFlags', $aExtraParams)) {
$aExtraParams['fieldsFlags'] = [];
@@ -64,13 +63,13 @@ class FormHelper
$aExtraParams['fieldsComments'] = [];
}
// Iterate throw class attributes...
// Iterate through class attributes...
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
// Set attribute blobs in read only
if ($oAttDef instanceof AttributeBlob) {
$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)
$oPage->add_script("if (! window.CKEDITOR_BASEPATH) { var CKEDITOR_BASEPATH = '".utils::GetAbsoluteUrlAppRoot()."js/ckeditor/';}");
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
{
foreach (static::GetCSSFilesRelPathsForC3JS() as $sFile) {
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().$sFile);
$oPage->LinkStylesheetFromAppRoot($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
{
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/raphael-min.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/fraphael.js');
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery-contextmenu/src/jquery.contextMenu.css');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery-contextmenu/src/jquery.contextMenu.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.popupmenu.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.mousewheel.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/simple_graph.js');
$oPage->LinkScriptFromAppRoot('js/raphael-min.js');
$oPage->LinkScriptFromAppRoot('js/fraphael.js');
$oPage->LinkStylesheetFromAppRoot('node_modules/jquery-contextmenu/src/jquery.contextMenu.css');
$oPage->LinkScriptFromAppRoot('node_modules/jquery-contextmenu/src/jquery.contextMenu.js');
$oPage->LinkScriptFromAppRoot('js/jquery.positionBy.js');
$oPage->LinkScriptFromAppRoot('js/jquery.popupmenu.js');
$oPage->LinkScriptFromAppRoot('js/jquery.mousewheel.js');
$oPage->LinkScriptFromAppRoot('js/simple_graph.js');
}
}

View File

@@ -26,10 +26,10 @@ class ErrorPage extends NiceWebPage
{
$oKpi = new ExecutionKPI();
parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js");
$this->add_linked_script("../setup/setup.js");
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css');
$this->LinkScriptFromAppRoot("js/jquery.blockUI.js");
$this->LinkScriptFromAppRoot("setup/setup.js");
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
$this->add_saas("css/setup.scss");
$oKpi->ComputeStats(get_class($this).' creation', 'ErrorPage');
}
@@ -58,7 +58,7 @@ class ErrorPage extends NiceWebPage
if(utils::IsEasterEggAllowed())
{
$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->log_error($sText);

View File

@@ -152,20 +152,20 @@ JS
parent::InitializeLinkedScripts();
// Used throughout the app.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery/dist/jquery.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.blockUI.js');
$this->LinkScriptFromAppRoot('node_modules/jquery/dist/jquery.min.js');
$this->LinkScriptFromAppRoot('js/jquery.blockUI.js');
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->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.dev.js');
$this->LinkScriptFromAppRoot('js/jquery-migrate.dev-params.js');
$this->LinkScriptFromAppRoot('js/jquery-migrate.dev.js');
} 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.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/latinise/latinise.min.js');
$this->LinkScriptFromAppRoot('js/utils.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: Reuse theming mechanism for Full Moon
$sCssThemeUrl = ThemeHandler::GetCurrentThemeUrl();
$this->add_linked_stylesheet($sCssThemeUrl);
$this->LinkStylesheetFromURI($sCssThemeUrl);
}
protected function GetReadyScriptsStartedTrigger(): ?string

View File

@@ -77,18 +77,17 @@ class UnauthenticatedWebPage extends NiceWebPage
$this->SetContentType('text/html');
// - 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
$sMomentURL = utils::GetAbsoluteUrlAppRoot().'/js/moment-with-locales.min.js';
$this->add_linked_script($sMomentURL);
$this->LinkScriptFromAppRoot('js/moment-with-locales.min.js');
$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
$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_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
$this->add_saas('css/unauthenticated.scss');
@@ -279,13 +278,13 @@ class UnauthenticatedWebPage extends NiceWebPage
*/
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
$this->add_saas('css/unauthenticated.scss');
// Custom theme to allow admin to override the default one.
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 ExecutionKPI;
use IssueLog;
use LogChannels;
use MetaModel;
use Symfony\Component\HttpFoundation\Response;
use UserRights;
use utils;
use const APPROOT;
use const MODULESROOT;
/**
@@ -73,6 +76,17 @@ class WebPage implements Page
*/
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
* @since 3.0.0
@@ -512,6 +526,109 @@ class WebPage implements Page
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
*
@@ -735,15 +852,77 @@ class WebPage implements Page
* 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
*
* @uses WebPage::$a_linked_scripts
* @param string $s_linked_script
* @param string $sLinkedScriptAbsUrl
*
* @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))) {
$this->a_linked_scripts[$s_linked_script] = $s_linked_script;
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
// 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
* 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 $s_condition
* @param string $sLinkedStylesheet
* @param string $sCondition
* @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 = '../';
}
$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();
// 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
$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.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'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.min.js');
$this->LinkScriptFromAppRoot('js/jquery-ui-timepicker-addon-i18n.min.js');
// Used by external keys and other drop down lists
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/selectize-plugin-a11y/selectize-plugin-a11y.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.multiselect.js');
$this->LinkScriptFromAppRoot('js/selectize.min.js');
$this->LinkScriptFromAppRoot('node_modules/selectize-plugin-a11y/selectize-plugin-a11y.js');
$this->LinkScriptFromAppRoot('js/jquery.multiselect.js');
// 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, ...
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/moment-with-locales.min.js');
$this->LinkScriptFromAppRoot('js/moment-with-locales.min.js');
// 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
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'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/@popperjs/core/dist/umd/popper.min.js');
$this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.min.js');
// 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
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/mousetrap/mousetrap.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'node_modules/mousetrap/plugins/record/mousetrap-record.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/keyboard-shortcuts.js');
$this->LinkScriptFromAppRoot('node_modules/mousetrap/mousetrap.min.js');
$this->LinkScriptFromAppRoot('node_modules/mousetrap/plugins/record/mousetrap-record.min.js');
$this->LinkScriptFromAppRoot('js/pages/backoffice/keyboard-shortcuts.js');
// Used throughout the app.
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/toolbox.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/pages/backoffice/on-ready.js');
$this->LinkScriptFromAppRoot('js/pages/backoffice/toolbox.js');
$this->LinkScriptFromAppRoot('js/pages/backoffice/on-ready.js');
// Used by dashboard editor
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/property_field.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/icon_select.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/ajaxfileupload.js');
$this->LinkScriptFromAppRoot('js/property_field.js');
$this->LinkScriptFromAppRoot('js/icon_select.js');
$this->LinkScriptFromAppRoot('js/ajaxfileupload.js');
}
/**
@@ -257,24 +257,24 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
parent::InitializeLinkedStylesheets();
// 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
$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
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'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/dist/tippy.css');
$this->LinkStylesheetFromAppRoot('node_modules/tippy.js/animations/shift-away-subtle.css');
// Icons
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-combodo/font-combodo.css');
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.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}
$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
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css');
$this->LinkStylesheetFromAppRoot('css/selectize.default.css');
}
/**
@@ -871,7 +871,7 @@ HTML;
/** @var \iBackofficeLinkedScriptsExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iBackofficeLinkedScriptsExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->GetLinkedScriptsAbsUrls() as $sScriptUrl) {
$this->add_linked_script($sScriptUrl);
$this->LinkScriptFromURI($sScriptUrl);
}
}
// - API: Early inline scripts
@@ -898,7 +898,7 @@ HTML;
/** @var \iBackofficeLinkedStylesheetsExtension $oExtensionInstance */
foreach (MetaModel::EnumPlugins('iBackofficeLinkedStylesheetsExtension') as $oExtensionInstance) {
foreach ($oExtensionInstance->GetLinkedStylesheetsAbsUrls() as $sStylesheetUrl) {
$this->add_linked_stylesheet($sStylesheetUrl);
$this->LinkStylesheetFromURI($sStylesheetUrl);
}
}
// - API: Inline style

View File

@@ -54,7 +54,7 @@ class iTopWizardWebPage extends iTopWebPage
$sStyle = ($iIndex == $this->m_iCurrentStep) ? 'wizActiveStep' : 'wizStep';
$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>";
parent::output();
}

View File

@@ -845,7 +845,7 @@ EOF
);
$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><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>");
self::DisplayAboutLicenses($oPage);
@@ -927,7 +927,7 @@ EOF
// Display
//
$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>");

View File

@@ -315,7 +315,7 @@ JS;
}
// - JS files
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
@@ -771,7 +771,7 @@ JS;
protected function AddRequiredForModificationJsFilesToPage(iTopWebPage &$oPage): void
{
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()
{
$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
// Make bulk actions block
$oBulkActionsBlock = PanelUIBlockFactory::MakeForInformation(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Title'));
@@ -233,10 +233,6 @@ $.ajax({
type: 'POST',
success: function(data) {
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');
CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.read');
@@ -273,12 +269,6 @@ $.ajax({
type: 'POST',
success: function(data) {
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');
CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.unread');
@@ -384,15 +374,15 @@ JS
$oEventBlock->SetIcon($sIconUrl, Panel::ENUM_ICON_COVER_METHOD_COVER,true);
}
// Prepare Event actions
$oMarkAsReadPopoverMenu = new PopoverMenu();
$oMarkAsUnreadPopoverMenu = new PopoverMenu();
// Common actions
$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',
Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'),
'UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'
);
$oDeleteButton->SetOnClickJsCode(
<<<JS
let oSelf = this;
@@ -410,31 +400,26 @@ $.ajax({
}
}
});
JS,
'_blank'
);
$oViewButton = new URLPopupMenuItem(
'UI:Newsroom:iTopNotification:ViewAllPage:Action:ViewObject:Label',
JS
)
->SetIconClass('fas fa-trash-alt')
->SetTooltip(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:Delete:Label'));
$oViewButton = ButtonUIBlockFactory::MakeIconLink('fas fa-external-link-alt',
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'
);
// Mark as read action
$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'
);
// Mark as read action
$oMarkAsReadPopoverMenu->AddItem('more-actions', PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oViewButton))->SetContainer(PopoverMenu::ENUM_CONTAINER_PARENT);
$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);
$oMarkAsReadButton->AddCSSClass('ibo-notifications--view-all--read-action')
->SetIconClass('far fa-envelope-open')
->SetTooltip(Dict::S('UI:Newsroom:iTopNotification:ViewAllPage:Action:MarkAsRead:Label'));
// Mark as unread action
$sMarkAsReadUrl = Router::GetInstance()->GenerateUrl(self::ROUTE_NAMESPACE.'.mark_as_read', ['notification_id' => $oEvent->GetKey(), 'token' => $sCSRFToken]);
@@ -446,8 +431,6 @@ JS,
type: 'POST',
success: function(data) {
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');
CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.read');
@@ -460,13 +443,14 @@ JS,
JS
);
$oMarkAsReadButtonGroup = ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu($oMarkAsReadButton, $oMarkAsReadPopoverMenu);
$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'
);
$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]);
$oMarkAsUnreadButton->SetOnClickJsCode(
<<<JS
@@ -476,8 +460,6 @@ JS
type: 'POST',
success: function(data) {
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');
CombodoToast.OpenSuccessToast(data.message);
$('.ibo-notifications--view-all--container').trigger('itop.notification.unread');
@@ -489,25 +471,18 @@ JS
});
JS
);
$oMarkAsUnreadButtonGroup = ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu($oMarkAsUnreadButton, $oMarkAsUnreadPopoverMenu);
// Add actions to the object summary block and remove old button
$oOldButtonId = $oEventBlock->GetActions()->GetId();
$oEventBlock->RemoveSubBlock($oOldButtonId);
$oEventBlock->SetToolBlocks([$oMarkAsReadButtonGroup, $oMarkAsUnreadButtonGroup]);
$oEventBlock->SetToolBlocks([$oMarkAsUnreadButton, $oMarkAsReadButton, $oViewButton, $oDeleteButton]);
$oActionsBlock = new UIContentBlock();
$oActionsBlock->AddSubBlock($oMarkAsReadButtonGroup);
$oActionsBlock->AddSubBlock($oMarkAsUnreadButtonGroup);
$oActionsBlock->AddSubBlock($oMarkAsUnreadButton);
$oActionsBlock->AddSubBlock($oMarkAsReadButton);
$oActionsBlock->AddSubBlock($oViewButton);
$oActionsBlock->AddSubBlock($oDeleteButton);
$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);
}

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
foreach (Set::DEFAULT_JS_FILES_REL_PATH as $sJsFile) {
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().$sJsFile);
$oPage->LinkScriptFromAppRoot($sJsFile);
}
$oPage->AddSubBlock($oNotificationsPanel);

View File

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

View File

@@ -3,7 +3,7 @@
{% apply spaceless %}
<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%">
<img src="../images/indicator.gif">
<img src="{{ get_absolute_url_app_root() }}images/indicator.gif">
</div>
</div>
{% 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
);
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/tabularfieldsselector.js');
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.dragtable.js');
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/dragtable.css');
$oP->LinkScriptFromAppRoot('js/tabularfieldsselector.js');
$oP->LinkScriptFromAppRoot('js/jquery.dragtable.js');
$oP->LinkStylesheetFromAppRoot('css/dragtable.css');
$oForm = FormUIBlockFactory::MakeStandard("export-form");
$oForm->SetAction($sAction);
@@ -707,8 +707,8 @@ try
$oP = new NiceWebPage('iTop export');
$oP->add_http_headers();
$oP->add_ready_script("$('table.listResults').tablesorter({widgets: ['MyZebra']});");
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'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/all.min.css');
$oP->LinkStylesheetFromAppRoot('css/font-awesome/css/v4-shims.min.css');
} else {
$oP = new WebPage('iTop export');
$oP->add_http_headers();

View File

@@ -219,8 +219,8 @@ if (!empty($sExpression))
case 'html':
$oP = new NiceWebPage("iTop - Export");
$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->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css');
$oP->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
$oP->LinkStylesheetFromAppRoot('css/font-awesome/css/v4-shims.min.css');
// 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