diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index a9209de36..852e4b97a 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -35,6 +35,7 @@ use Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\ActivityPanel; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\Column; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumn; use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectFactory; +use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab; use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock; use Combodo\iTop\Renderer\BlockRenderer; use Combodo\iTop\Renderer\Console\ConsoleFormRenderer; @@ -543,7 +544,11 @@ EOF { continue; } - $oPage->AddAjaxTab($oAttDef->GetLabel(), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=dashboard&class='.get_class($this).'&id='.$this->GetKey().'&attcode='.$oAttDef->GetCode(), true, 'Class:'.$sClass.'/Attribute:'.$sAttCode); + $oPage->AddAjaxTab($oAttDef->GetLabel(), + utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=dashboard&class='.get_class($this).'&id='.$this->GetKey().'&attcode='.$oAttDef->GetCode(), + true, + 'Class:'.$sClass.'/Attribute:'.$sAttCode, + AjaxTab::ENUM_TAB_PLACEHOLDER_REL_PATH_DASHBOARD); continue; } diff --git a/datamodels/2.x/itop-tickets/main.itop-tickets.php b/datamodels/2.x/itop-tickets/main.itop-tickets.php index d4003bf42..97c516855 100755 --- a/datamodels/2.x/itop-tickets/main.itop-tickets.php +++ b/datamodels/2.x/itop-tickets/main.itop-tickets.php @@ -15,6 +15,7 @@ // // You should have received a copy of the GNU Affero General Public License // along with iTop. If not, see +use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab; /** @@ -284,7 +285,7 @@ class _Ticket extends cmdbAbstractObject $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/jquery.contextMenu.css'); $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.contextMenu.js'); $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/simple_graph.js'); - $oPage->AddAjaxTab('Ticket:ImpactAnalysis', utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=ticket_impact&class='.get_class($this).'&id='.$this->GetKey(), true); + $oPage->AddAjaxTab('Ticket:ImpactAnalysis', utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=ticket_impact&class='.get_class($this).'&id='.$this->GetKey(), true, null, AjaxTab::ENUM_TAB_PLACEHOLDER_REL_PATH_MISC); } } } diff --git a/images/placeholders/skeleton-dashboard.svg b/images/placeholders/skeleton-dashboard.svg new file mode 100644 index 000000000..dc983f113 --- /dev/null +++ b/images/placeholders/skeleton-dashboard.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/placeholders/skeleton-list.svg b/images/placeholders/skeleton-list.svg new file mode 100644 index 000000000..9dd438647 --- /dev/null +++ b/images/placeholders/skeleton-list.svg @@ -0,0 +1,81 @@ + + Loading... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/placeholders/skeleton-object.svg b/images/placeholders/skeleton-object.svg new file mode 100644 index 000000000..964b016c4 --- /dev/null +++ b/images/placeholders/skeleton-object.svg @@ -0,0 +1,87 @@ + + Loading... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/placeholders/skeleton.svg b/images/placeholders/skeleton.svg index 8c945d230..2e8e4e6df 100644 --- a/images/placeholders/skeleton.svg +++ b/images/placeholders/skeleton.svg @@ -1,48 +1,42 @@ - Loading... - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + ' + tab.text() + ''); - var oTempDiv = $('
').addClass('ibo-tab--temporary-remote-content') - var oPlaceholder = $('
').addClass('ibo-tab--temporary-remote-content--placeholder').load(GetAbsoluteUrlAppRoot()+'images/placeholders/skeleton.svg'); - var oLoadButton = $('
').addClass('ibo-tab--temporary-remote-content--button').text(placeholder).on('click', function(){tab.find('a').click()}) + let oTempDiv = $('
').addClass('ibo-tab--temporary-remote-content') + let oPlaceholder = $('
').addClass('ibo-tab--temporary-remote-content--placeholder').load(tab.attr('data-placeholder')); + let oLoadButton = $('
').addClass('ibo-tab--temporary-remote-content--button').text(placeholder).on('click', function(){tab.find('a').click()}) oTempDiv.append(oPlaceholder) oTempDiv.append(oLoadButton) panel.append(oTempDiv); diff --git a/pages/csvimport.php b/pages/csvimport.php index 8fcc0c97d..1d3ad427e 100644 --- a/pages/csvimport.php +++ b/pages/csvimport.php @@ -17,6 +17,8 @@ * You should have received a copy of the GNU Affero General Public License */ +use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab; + try { ini_set('memory_limit', '256M'); @@ -1438,7 +1440,7 @@ EOF if (Utils::GetConfig()->Get('csv_import_history_display')) { $oPage->SetCurrentTabContainer('tabs1'); - $oPage->AddAjaxTab('UI:History:BulkImports', utils::GetAbsoluteUrlAppRoot().'pages/csvimport.php?step=11', true /* bCache */); + $oPage->AddAjaxTab('UI:History:BulkImports', utils::GetAbsoluteUrlAppRoot().'pages/csvimport.php?step=11', true /* bCache */, null, AjaxTab::ENUM_TAB_PLACEHOLDER_REL_PATH_MISC); } } diff --git a/sources/application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php b/sources/application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php index a87568864..86b5a3fa9 100644 --- a/sources/application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php +++ b/sources/application/UI/Base/Layout/TabContainer/Tab/AjaxTab.php @@ -24,6 +24,7 @@ use Combodo\iTop\Application\UI\Base\iUIBlock; use Combodo\iTop\Application\UI\Base\UIException; use Dict; use TabManager; +use utils; /** * Class AjaxTab @@ -33,15 +34,37 @@ use TabManager; * @since 3.0.0 */ class AjaxTab extends Tab { + + const ENUM_TAB_PLACEHOLDER_REL_PATH_LIST = 'images/placeholders/skeleton-list.svg'; + const ENUM_TAB_PLACEHOLDER_REL_PATH_DASHBOARD = 'images/placeholders/skeleton-dashboard.svg'; + const ENUM_TAB_PLACEHOLDER_REL_PATH_OBJECT = 'images/placeholders/skeleton-object.svg'; + const ENUM_TAB_PLACEHOLDER_REL_PATH_MISC = 'images/placeholders/skeleton.svg'; + + const DEFAULT_TAB_PLACEHOLDER_REL_PATH = self::ENUM_TAB_PLACEHOLDER_REL_PATH_MISC; + // Overloaded constants public const BLOCK_CODE = 'ibo-ajax-tab'; public const TAB_TYPE = TabManager::ENUM_TAB_TYPE_AJAX; + /** @var string Placeholder displayed before tab is loaded */ + private $sPlaceholderRelPath; /** @var string The target URL to be loaded asynchronously */ private $sUrl; /** @var bool Whether the tab should should be cached by the browser or always refreshed */ private $bCache; + /** + * Tab constructor. + * + * @param string $sTabCode + * @param string $sTitle + * @param string $sPlaceholderRelPath + */ + public function __construct(string $sTabCode, string $sTitle, string $sPlaceholderRelPath = AjaxTab::DEFAULT_TAB_PLACEHOLDER_REL_PATH) + { + parent::__construct($sTabCode, $sTitle); + $this->sPlaceholderRelPath = $sPlaceholderRelPath; + } /** * @param string $sUrl * @@ -82,6 +105,35 @@ class AjaxTab extends Tab { return $this->bCache ? 'true' : 'false'; } + /** + * + * @param string $sPlaceholderRelPath + * + * @return $this + */ + public function SetPlaceholderRelPath(string $sPlaceholderRelPath) { + $this->sPlaceholderRelPath = $sPlaceholderRelPath; + + return $this; + } + + /** + * + * @return string + */ + public function GetPlaceholderRelPath(): string { + return $this->sPlaceholderRelPath; + } + + /** + * + * @return string + * @throws \Exception + */ + public function GetPlaceholderAbsPath(): string { + return utils::GetAbsoluteUrlAppRoot().$this->sPlaceholderRelPath; + } + //------------------------------- // iUIBlock implementation //------------------------------- diff --git a/sources/application/UI/Base/Layout/TabContainer/TabContainer.php b/sources/application/UI/Base/Layout/TabContainer/TabContainer.php index 01ac20240..cabad41c2 100644 --- a/sources/application/UI/Base/Layout/TabContainer/TabContainer.php +++ b/sources/application/UI/Base/Layout/TabContainer/TabContainer.php @@ -113,13 +113,17 @@ class TabContainer extends UIContentBlock /** * @param string $sTabCode * @param string $sTitle + * @param string|null $sPlaceholder * * @return \Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\Tab * @throws \Combodo\iTop\Application\UI\Base\UIException */ - public function AddAjaxTab(string $sTabCode, string $sTitle): Tab + public function AddAjaxTab(string $sTabCode, string $sTitle, ?string $sPlaceholder = null): Tab { - $oTab = new AjaxTab($sTabCode, $sTitle); + if($sPlaceholder === null){ + $sPlaceholder = AjaxTab::DEFAULT_TAB_PLACEHOLDER_REL_PATH; + } + $oTab = new AjaxTab($sTabCode, $sTitle, $sPlaceholder); $this->AddSubBlock($oTab); return $oTab; } diff --git a/sources/application/WebPage/TabManager.php b/sources/application/WebPage/TabManager.php index f8917ec8b..607d24df8 100644 --- a/sources/application/WebPage/TabManager.php +++ b/sources/application/WebPage/TabManager.php @@ -5,6 +5,7 @@ */ use Combodo\iTop\Application\UI\Base\iUIBlock; +use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab; use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\Tab; use Combodo\iTop\Application\UI\Base\Layout\TabContainer\TabContainer; @@ -198,17 +199,18 @@ class TabManager * the tab to be reloaded upon each activation. * * @param string|null $sTabTitle + * @param string $sPlaceholder * * @return string * * @throws \Combodo\iTop\Application\UI\Base\UIException * @since 2.0.3 */ - public function AddAjaxTab(string $sTabCode, string $sUrl, bool $bCache = true, string $sTabTitle = null): string + public function AddAjaxTab(string $sTabCode, string $sUrl, bool $bCache = true, string $sTabTitle = null, string $sPlaceholder = null): string { // Set the content of the tab /** @var \Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab $oTab */ - $oTab = $this->InitTab($this->m_sCurrentTabContainer, $sTabCode, static::ENUM_TAB_TYPE_AJAX, $sTabTitle); + $oTab = $this->InitTab($this->m_sCurrentTabContainer, $sTabCode, static::ENUM_TAB_TYPE_AJAX, $sTabTitle, $sPlaceholder); $oTab->SetUrl($sUrl) ->SetCache($bCache); @@ -311,12 +313,13 @@ class TabManager * @param string $sTabCode * @param string $sTabType * @param string|null $sTabTitle + * @param string|null $sPlaceholder * * @return \Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\Tab * @throws \Combodo\iTop\Application\UI\Base\UIException * @since 2.7.0 */ - protected function InitTab(string $sTabContainer, string $sTabCode, string $sTabType = self::DEFAULT_TAB_TYPE, string $sTabTitle = null): Tab + protected function InitTab(string $sTabContainer, string $sTabCode, string $sTabType = self::DEFAULT_TAB_TYPE, string $sTabTitle = null, string $sPlaceholder = null): Tab { $oTab = null; if (!$this->TabExists($sTabContainer, $sTabCode)) { @@ -330,7 +333,7 @@ class TabManager switch ($sTabType) { case static::ENUM_TAB_TYPE_AJAX: - $oTab = $oTabContainer->AddAjaxTab($sTabCode, $sTitle); + $oTab = $oTabContainer->AddAjaxTab($sTabCode, $sTitle, $sPlaceholder); break; case static::ENUM_TAB_TYPE_HTML: diff --git a/sources/application/WebPage/iTopWebPage.php b/sources/application/WebPage/iTopWebPage.php index fe5eee613..bacb141a1 100644 --- a/sources/application/WebPage/iTopWebPage.php +++ b/sources/application/WebPage/iTopWebPage.php @@ -1045,9 +1045,9 @@ EOF * @throws \Exception * @since 2.0.3 */ - public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null) + public function AddAjaxTab($sTabCode, $sUrl, $bCache = true, $sTabTitle = null, $sPlaceholder = null) { - $this->add($this->m_oTabs->AddAjaxTab($sTabCode, $sUrl, $bCache, $sTabTitle)); + $this->add($this->m_oTabs->AddAjaxTab($sTabCode, $sUrl, $bCache, $sTabTitle, $sPlaceholder)); } /** diff --git a/templates/base/layouts/tab-container/layout.html.twig b/templates/base/layouts/tab-container/layout.html.twig index f205446c3..eefef2995 100644 --- a/templates/base/layouts/tab-container/layout.html.twig +++ b/templates/base/layouts/tab-container/layout.html.twig @@ -12,7 +12,8 @@
  • + data-cache="{{ oTab.GetCache() }}" + data-placeholder="{{ oTab.GetPlaceholderAbsPath() }}"> {{ oTab.GetTitle() }}