mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Proposition that allows to include modules from ar array. Works both on usual page + ajax page
This commit is contained in:
@@ -15,6 +15,15 @@ class TurboForm extends UIContentBlock
|
||||
// Overloaded constants
|
||||
public const BLOCK_CODE = 'ibo-form';
|
||||
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/components/turbo-form/layout';
|
||||
public const DEFAULT_JS_MODULES_CONFIG = [
|
||||
[
|
||||
'sModuleName' => 'session',
|
||||
'sJsModuleSrc' => '/node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js',
|
||||
'sModuleConfigJs' => <<<JS
|
||||
session.drive = false;
|
||||
JS
|
||||
],
|
||||
];
|
||||
|
||||
/** @var string|null */
|
||||
protected ?string $sOnSubmitJsCode;
|
||||
|
||||
@@ -65,6 +65,11 @@ abstract class UIBlock implements iUIBlock
|
||||
public const DEFAULT_JS_FILES_REL_PATH = [
|
||||
'js/ui-block.js',
|
||||
];
|
||||
/**
|
||||
* @var array
|
||||
* @see static::$aJsModulesConfig
|
||||
*/
|
||||
public const DEFAULT_JS_MODULES_CONFIG = [];
|
||||
/**
|
||||
* @var string|null Relative path (from <ITOP>/templates/) to the "on init" JS template
|
||||
* @see static::$aJsTemplatesRelPath
|
||||
@@ -138,6 +143,11 @@ abstract class UIBlock implements iUIBlock
|
||||
* and not in {@see static::DEFAULT_JS_TEMPLATE_REL_PATH} ! Indeed the later is output before external files loading.
|
||||
*/
|
||||
protected $aJsFilesRelPath = [];
|
||||
/**
|
||||
* @var array Relative paths (from <ITOP>/) to the external JS module files to include in the page.
|
||||
* @description Used to include JS file that contains modules + the JS code assocciated to these modules. Even if you use only a few modules, the whole JS file will be loaded.
|
||||
*/
|
||||
protected $aJsModulesConfig = [];
|
||||
/**
|
||||
* @var array
|
||||
* @see iUIBlock::GetCssFilesRelPaths()
|
||||
@@ -182,6 +192,9 @@ abstract class UIBlock implements iUIBlock
|
||||
$this->AddMultipleJsFilesRelPaths(static::DEFAULT_JS_FILES_REL_PATH);
|
||||
}
|
||||
|
||||
$this->AddMultipleJsModulesFilesRelPaths(static::DEFAULT_JS_MODULES_CONFIG);
|
||||
|
||||
|
||||
// Add external CSS files
|
||||
// 1) From ancestors if they are required
|
||||
if (static::REQUIRES_ANCESTORS_DEFAULT_CSS_FILES) {
|
||||
@@ -253,6 +266,15 @@ abstract class UIBlock implements iUIBlock
|
||||
return $this->aJsFilesRelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function GetJsModuleConfigs(): array
|
||||
{
|
||||
return $this->aJsModulesConfig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -316,6 +338,31 @@ abstract class UIBlock implements iUIBlock
|
||||
return $this->GetFilesUrlRecursively(static::ENUM_BLOCK_FILES_TYPE_JS, $bAbsoluteUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetJsModulesRecursively(bool $bAbsoluteUrl = false): array
|
||||
{
|
||||
$aJsModulesConfigs = [];
|
||||
|
||||
// Files from the block itself
|
||||
foreach ($this->GetJsModuleConfigs() as $sJsCurrentModuleBlockConfig) {
|
||||
$aJsModulesConfigs[] = $sJsCurrentModuleBlockConfig;
|
||||
}
|
||||
|
||||
// Files from its sub blocks
|
||||
foreach ($this->GetSubBlocks() as $sSubBlockName => $oSubBlock) {
|
||||
/** @noinspection SlowArrayOperationsInLoopInspection */
|
||||
$aJsModulesConfigs = array_merge(
|
||||
$aJsModulesConfigs,
|
||||
$oSubBlock->GetJsModulesRecursively($bAbsoluteUrl)
|
||||
);
|
||||
}
|
||||
|
||||
return $aJsModulesConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
@@ -354,6 +401,16 @@ abstract class UIBlock implements iUIBlock
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function AddJsModuleConfigs(array $aModuleConfig)
|
||||
{
|
||||
$this->aJsModulesConfig[] = $aModuleConfig;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -366,6 +423,18 @@ abstract class UIBlock implements iUIBlock
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function AddMultipleJsModulesFilesRelPaths(array $aModulesConfig)
|
||||
{
|
||||
foreach ($aModulesConfig as $aModuleConfig) {
|
||||
$this->AddJsModuleConfigs($aModuleConfig);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
||||
@@ -135,6 +135,15 @@ interface iUIBlock
|
||||
*/
|
||||
public function AddJsFileRelPath(string $sPath);
|
||||
|
||||
/**
|
||||
* Add a JS module file (whole files inclusion + module configuration) to a block
|
||||
*
|
||||
* @param array $aModuleConfig relative path of a JS file to add
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function AddJsModuleConfigs(array $aModuleConfig);
|
||||
|
||||
/**
|
||||
* Add several JS files to a block.
|
||||
* Duplicates will not be added.
|
||||
@@ -145,6 +154,15 @@ interface iUIBlock
|
||||
*/
|
||||
public function AddMultipleJsFilesRelPaths(array $aPaths);
|
||||
|
||||
/**
|
||||
* Add several JS modules files to a block.
|
||||
*
|
||||
* @param string[] $aModulesConfig
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function AddMultipleJsModulesFilesRelPaths(array $aModulesConfig);
|
||||
|
||||
/**
|
||||
* Add a CSS file to a block (if not already present)
|
||||
*
|
||||
|
||||
@@ -215,6 +215,7 @@ class AjaxPage extends WebPage implements iTabbedPage
|
||||
'aCssFiles' => $this->a_linked_stylesheets,
|
||||
'aCssInline' => $this->a_styles,
|
||||
'aJsFiles' => $this->a_linked_scripts,
|
||||
'aJsFilesModules' => $this->a_linked_modules_config,
|
||||
'aJsInlineLive' => $this->a_scripts,
|
||||
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
|
||||
'aJsInlineOnInit' => $this->a_init_scripts,
|
||||
|
||||
@@ -141,6 +141,7 @@ JS
|
||||
protected function InitializeLinkedScripts(): void
|
||||
{
|
||||
parent::InitializeLinkedScripts();
|
||||
parent::InitializeLinkedModulesScript();
|
||||
|
||||
// Used throughout the app.
|
||||
$this->LinkScriptFromAppRoot('node_modules/jquery/dist/jquery.min.js');
|
||||
|
||||
@@ -170,8 +170,12 @@ class WebPage implements Page
|
||||
* @var array Scripts to be executed when the DOM is ready, with a slight delay, after the "init scripts"
|
||||
*/
|
||||
protected $a_ready_scripts;
|
||||
/** @var array Scripts linked (externals) to the page through URIs */
|
||||
/** @var array Scripts linked to the page through URIs */
|
||||
protected $a_linked_scripts;
|
||||
|
||||
/** @var array Modules that comes from script */
|
||||
public $a_linked_modules_config;
|
||||
|
||||
/** @var array Specific dictionary entries to be used client side */
|
||||
protected $a_dict_entries;
|
||||
/** @var array Sub-sets of dictionary entries (based on the given prefix) for the client side */
|
||||
@@ -233,6 +237,7 @@ class WebPage implements Page
|
||||
$this->InitializeInitScripts();
|
||||
$this->InitializeReadyScripts();
|
||||
$this->InitializeLinkedScripts();
|
||||
$this->InitializeLinkedModulesScript();
|
||||
$this->InitializeDictEntries();
|
||||
$this->InitializeStyles();
|
||||
$this->InitializeLinkedStylesheets();
|
||||
@@ -872,6 +877,19 @@ class WebPage implements Page
|
||||
$this->a_linked_scripts = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty all base linked modules for the page
|
||||
*
|
||||
* @return void
|
||||
* @uses WebPage::$a_a_linked_modules
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected function EmptyLinkedModulesScript(): void
|
||||
{
|
||||
$this->a_linked_modules_config = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize base linked scripts for the page
|
||||
*
|
||||
@@ -884,6 +902,18 @@ class WebPage implements Page
|
||||
$this->EmptyLinkedScripts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize base linked scripts for the page
|
||||
*
|
||||
* @uses WebPage::$a_linked_a_linked_modules
|
||||
* @return void
|
||||
* @since 3.0.0
|
||||
*/
|
||||
protected function InitializeLinkedModulesScript(): void
|
||||
{
|
||||
$this->EmptyLinkedModulesScript();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to include JS files from the iTop package (e.g. `<ITOP>/js/*`)
|
||||
*
|
||||
@@ -905,6 +935,28 @@ class WebPage implements Page
|
||||
$this->LinkResourceFromAppRoot($sFileRelPath, static::ENUM_RESOURCE_TYPE_JS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to include JS modules (and configuration) from the iTop package (e.g. `<ITOP>/js/*`)
|
||||
*
|
||||
* The provided JS code will be executed at step 2 of the JS execution chain:
|
||||
* early script ==> [linked script] ==> script ==> init script ==> ready script
|
||||
*
|
||||
* @api-advanced
|
||||
* @see static::add_early_script, static::add_script, static::add_init_script, static::add_ready_script
|
||||
* @see static::LinkScriptFromURI, static::LinkScriptFromModule
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public function LinkModuleFromAppRoot(string $sFileRelPath): void
|
||||
{
|
||||
// TODO adapt with array method
|
||||
$this->LinkResourceFromAppRoot($sFileRelPath, static::ENUM_RESOURCE_TYPE_JS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to include JS files from any module
|
||||
*
|
||||
@@ -1563,6 +1615,7 @@ JS;
|
||||
'aCssInline' => $this->a_styles,
|
||||
'aJsInlineEarly' => $this->a_early_scripts,
|
||||
'aJsFiles' => $this->a_linked_scripts,
|
||||
'aJsModulesFiles' => $this->a_linked_modules_config,
|
||||
'aJsInlineLive' => $this->a_scripts,
|
||||
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
|
||||
'aJsInlineOnInit' => $this->a_init_scripts,
|
||||
|
||||
@@ -164,6 +164,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
protected function InitializeLinkedScripts(): void
|
||||
{
|
||||
parent::InitializeLinkedScripts();
|
||||
parent::InitializeLinkedModulesScript();
|
||||
|
||||
// Used by forms
|
||||
$this->LinkScriptFromAppRoot('js/leave_handler.js');
|
||||
@@ -926,6 +927,7 @@ HTML;
|
||||
'aCssInline' => $this->a_styles,
|
||||
'aJsInlineEarly' => $this->a_early_scripts,
|
||||
'aJsFiles' => $this->a_linked_scripts,
|
||||
'aJsFilesModules' => $this->a_linked_modules_config,
|
||||
'aJsInlineOnInit' => $this->a_init_scripts,
|
||||
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
|
||||
'aJsInlineLive' => $this->a_scripts,
|
||||
|
||||
@@ -85,6 +85,12 @@ class ConsoleBlockRenderer extends BlockRenderer
|
||||
foreach ($oBlock->GetJsFilesUrlRecursively(true) as $sFileAbsUrl) {
|
||||
$oPage->LinkScriptFromURI($sFileAbsUrl);
|
||||
}
|
||||
|
||||
// JS modules configurations
|
||||
foreach ($oBlock->GetJsModulesRecursively(true) as $sJsModuleConfig) {
|
||||
$oPage->a_linked_modules_config [] = $sJsModuleConfig;
|
||||
}
|
||||
|
||||
static::AddCssJsTemplatesToPageRecursively($oPage, $oBlock, $aContextParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
{# @copyright Copyright (C) 2010-2025 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
<script type="module">
|
||||
import {session} from "{{ aPage.sAbsoluteUrlAppRoot }}/node_modules/@hotwired/turbo/dist/turbo.es2017-esm.js";
|
||||
|
||||
session.drive = false;
|
||||
</script>
|
||||
|
||||
<turbo-frame id="{{ oUIBlock.GetId() }}">
|
||||
<turbo-frame id="{{ oUIBlock.GetId() }}">
|
||||
{% if oUIBlock.GetAction() %}
|
||||
{{ form_start(oUIBlock.GetFormView(), {action: oUIBlock.GetAction()}) }}
|
||||
{% else %}
|
||||
|
||||
@@ -185,6 +185,20 @@
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% block iboPageJsModuleScripts %}
|
||||
{% if aPage.aJsFilesModules is not empty %}
|
||||
<script>
|
||||
console.log("aPage:", {{ aPage|raw }});
|
||||
</script>
|
||||
{% for aJsModule in aPage.aJsFilesModules %}
|
||||
<script type="module">
|
||||
import { {{ aJsModule.sModuleName }} } from "{{ aJsModule.sJsModuleSrc }}";
|
||||
{{ aJsModule.sModuleConfigJs|raw }}
|
||||
</script>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block iboPageCssFiles %}
|
||||
{% if aPage.aCssFiles is not empty %}
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -144,6 +144,21 @@ const aLoadedJsFilesResolveCallbacks = new Map();
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block iboPageJsModuleScripts %}
|
||||
|
||||
{% if aPage.aJsFilesModules is not empty %}
|
||||
<script>
|
||||
console.log("aPage:", {{ aPage|raw }});
|
||||
</script>
|
||||
{% for aJsModule in aPage.aJsFilesModules %}
|
||||
<script type="module">
|
||||
import { {{ aJsModule.sModuleName }} } from "{{ aJsModule.sJsModuleSrc }}";
|
||||
{{ aJsModule.sModuleConfigJs|raw }}
|
||||
</script>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block iboCapturedOutput %}
|
||||
{{ aPage.sCapturedOutput|raw }}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user