From 7e3b4af093184ea627cf9ca1b6f5cbb78c9b770e Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Fri, 21 Aug 2026 10:05:42 +0200 Subject: [PATCH] Fix JS file handling, add TODO for what's still missing --- .../backoffice/iPopupMenuExtension.php | 4 +-- css/backoffice/components/_field.scss | 14 ++++++++--- js/layouts/activity-panel/activity-panel.js | 2 +- .../Component/Button/ButtonUIBlockFactory.php | 25 +++++++++++++++++-- .../Component/Field/FieldUIBlockFactory.php | 11 ++++++-- .../ActivityPanelActionFactory.php | 3 ++- .../ActivityPanel/ActivityPanelFactory.php | 11 +++++--- .../TopBarQuickActionFactory.php | 7 +++++- 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/application/applicationextension/backoffice/iPopupMenuExtension.php b/application/applicationextension/backoffice/iPopupMenuExtension.php index 970cd4bf3d..0cb8b7e412 100644 --- a/application/applicationextension/backoffice/iPopupMenuExtension.php +++ b/application/applicationextension/backoffice/iPopupMenuExtension.php @@ -102,12 +102,12 @@ interface iPopupMenuExtension public const MENU_TOPBAR_ACTIONS = 11; /** * Get the list of items to be added to the actions on a given form field (i.e. the attribute of an object) - * $param is an array: ['object' => DBObject, att_code, mode=edit/read] + * $param is an array: ['object' => DBObject, att_code => attribute code , mode => edit/read] */ public const MENU_OBJDETAILS_FIELD_ACTIONS = 12; /** * Get the list of items to be added to the actions in the activity panel (read-only mode) - * $param = ['object' => DBObject, caselog_attcode => caselog attcode or 'activity'] + * $param = ['object' => DBObject, caselog_att_code => caselog attribute code or 'activity'] */ public const MENU_OBJDETAILS_ACTIVITY_PANEL_ACTIONS = 13; /** diff --git a/css/backoffice/components/_field.scss b/css/backoffice/components/_field.scss index 268ad82f0a..33bc5bb8df 100644 --- a/css/backoffice/components/_field.scss +++ b/css/backoffice/components/_field.scss @@ -266,9 +266,15 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default; @extend %ibo-hyperlink-inherited-colors; } -.ibo-field--action { - padding: 3px 6px; - ~ .ibo-field--action { - margin-left: 2px; +.ibo-field--label { + .ibo-field--action { + width: 20px; + height: 20px; + padding: 0; + border-radius: $ibo-field--fullscreen-toggler--border-radius; + font-size: $ibo-font-size-50; + ~ .ibo-field--action { + margin-left: 2px; + } } } diff --git a/js/layouts/activity-panel/activity-panel.js b/js/layouts/activity-panel/activity-panel.js index 70f6add62c..f8d22357b8 100644 --- a/js/layouts/activity-panel/activity-panel.js +++ b/js/layouts/activity-panel/activity-panel.js @@ -395,7 +395,7 @@ $(function() if (oActionElementMenuItem.length > 0) { // Note: Stop propagation to avoid the menu to be opened automatically by the popover handler oEvent.stopImmediatePropagation(); - + // TODO: Need fix for URL items as synthetic clicks doesn't open URLs oActionElementMenuItem.click(); } // Else let the popover menu open automatically, the user will have to choose a case log diff --git a/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php b/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php index 40686d5fde..884d9bd12c 100644 --- a/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php +++ b/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php @@ -381,20 +381,33 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory public static function MakeIconButtonFromApplicationPopupMenuItem($oPopupItem, $sColor = Button::ENUM_COLOR_SCHEME_NEUTRAL, $sActionType = Button::ENUM_ACTION_TYPE_ALTERNATIVE) { if ($oPopupItem instanceof JSPopupMenuItem) { + $sTooltip = $oPopupItem->GetTooltip(); + if (!utils::IsNotNullOrEmptyString($sTooltip)) { + $sTooltip = $oPopupItem->GetLabel(); + } + $oButton = self::MakeIconAction( $oPopupItem->GetIconClass(), - $oPopupItem->GetTooltip() + $sTooltip ); $oButton->SetOnClickJsCode($oPopupItem->GetJsCode()); + foreach ($oPopupItem->GetLinkedScripts() as $sLinkedScript) { + $oButton->AddJsFileRelPath($sLinkedScript); + } $oButton->SetActionType($sActionType); $oButton->SetColor($sColor); return $oButton; } elseif ($oPopupItem instanceof URLPopupMenuItem) { + $sTooltip = $oPopupItem->GetTooltip(); + if (!utils::IsNotNullOrEmptyString($sTooltip)) { + $sTooltip = $oPopupItem->GetLabel(); + } + $oButton = self::MakeIconLink( $oPopupItem->GetIconClass(), - $oPopupItem->GetTooltip(), + $sTooltip, $oPopupItem->GetURL(), $oPopupItem->GetTarget(), ); @@ -405,6 +418,8 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory return $oButton; } + //TODO How to handle other types of ApplicationPopupMenuItem? For now, we return null. + return null; } @@ -426,6 +441,10 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory $oButton->SetOnClickJsCode($oPopupItem->GetJsCode()); + foreach ($oPopupItem->GetLinkedScripts() as $sLinkedScript) { + $oButton->AddJsFileRelPath($sLinkedScript); + } + return $oButton; } elseif ($oPopupItem instanceof URLPopupMenuItem) { $oButton = self::MakeForLink( @@ -449,6 +468,8 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory return $oButton; } + //TODO How to handle other types of ApplicationPopupMenuItem? For now, we return null. + return null; } //---------------------------------------------------------------------------------------------- diff --git a/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php b/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php index 1f62aa511d..816b461962 100644 --- a/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php +++ b/sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php @@ -10,6 +10,7 @@ namespace Combodo\iTop\Application\UI\Base\Component\Field; use Combodo\iTop\Application\UI\Base\AbstractUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; +use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu; use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuFactory; use Combodo\iTop\Application\UI\Base\UIBlock; @@ -71,18 +72,24 @@ class FieldUIBlockFactory extends AbstractUIBlockFactory if (isset($aParams['actions'])) { //TODO make this a configuration parameter - $iMaxActions = 3; + $iMaxActions = 2; $aActions = []; // Create a button for a few action or a kebab button for multiple actions that a more than what's configured if (count($aParams['actions']) > $iMaxActions) { - $oKebabButton = ButtonUIBlockFactory::MakeIconAction('fa-ellipsis-v', 'More actions', 'kebab'); + $oKebabButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', 'More actions', 'kebab'); + $oKebabButton->AddCSSClass('ibo-field--action'); + $aKebabActions = []; foreach ($aParams['actions'] as $oAction) { $aKebabActions[] = $oAction->GetMenuItem(); } + //TODO: Make a dict entry for the kebab menu label $oKebabPopoverMenu = PopoverMenuFactory::MakeMenuForActions($oField->GetId().'--kebab-menu', $aKebabActions); + $oKebabPopoverMenu->SetTogglerFromBlock($oKebabButton); + $oKebabPopoverMenu->SetContainer(PopoverMenu::ENUM_CONTAINER_BODY); $aActions[] = $oKebabButton; + $aActions[] = $oKebabPopoverMenu; } else { foreach ($aParams['actions'] as $oAction) { $oActionButton = ButtonUIBlockFactory::MakeIconButtonFromApplicationPopupMenuItem($oAction); diff --git a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionFactory.php b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionFactory.php index 3d1d707b7a..46b020201f 100644 --- a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionFactory.php +++ b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionFactory.php @@ -88,7 +88,6 @@ class ActivityPanelActionFactory $oPopoverMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem($oPopupItemForPopoverMenuItem); $oPopoverMenuItem->AddDataAttribute('caselog-attribute-code', (string) $sSectionId); $aActionsByUid[$sUid]->GetPopoverMenu()->AddItem((string) $sSectionId, $oPopoverMenuItem); - $aActionsByUid[$sUid]->AddPopupItem((string) $sSectionId, $oPopupItem); } } @@ -124,6 +123,8 @@ class ActivityPanelActionFactory return $oAction; } + //TODO How to handle other types of ApplicationPopupMenuItem? For now, we return null. + return null; } diff --git a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php index 2f24d721d8..c3179d7de6 100644 --- a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php +++ b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php @@ -209,10 +209,13 @@ class ActivityPanelFactory $aActivityItems[] = $oMenuItem; } if (!empty($aActivityItems)) { - $aActionItems['activity'] = [ - 'label' => Dict::S('UI:Layout:ActivityPanel:Tab:Activity:Title'), - 'items' => $aActivityItems, - ]; + if (!array_key_exists('activity', $aActionItems)) { + $aActionItems['activity'] = [ + 'label' => Dict::S('UI:Layout:ActivityPanel:Tab:Activity:Title'), + 'items' => [], + ]; + } + $aActionItems['activity']['items'] = array_merge($aActionItems['activity']['items'], $aActivityItems); } } diff --git a/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionFactory.php b/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionFactory.php index 59f913c165..7317d0bbb3 100644 --- a/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionFactory.php +++ b/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionFactory.php @@ -32,7 +32,7 @@ use URLPopupMenuItem; */ class TopBarQuickActionFactory { - public static function MakeFromApplicationPopupItem($oApplicationPopupItem): TopBarQuickAction + public static function MakeFromApplicationPopupItem($oApplicationPopupItem) { if ($oApplicationPopupItem instanceof JSPopupMenuItem) { $oTopBarAction = new TopBarQuickActionJS( @@ -43,6 +43,8 @@ class TopBarQuickActionFactory ); $oTopBarAction->SetJsCode($oApplicationPopupItem->GetJsCode()); $oTopBarAction->SetUrl($oApplicationPopupItem->GetUrl()); + + $oTopBarAction->SetIncludeJSFiles($oApplicationPopupItem->GetLinkedScripts()); return $oTopBarAction; } elseif ($oApplicationPopupItem instanceof URLPopupMenuItem) { $oTopBarAction = new TopBarQuickActionURL( @@ -55,5 +57,8 @@ class TopBarQuickActionFactory $oTopBarAction->SetTarget($oApplicationPopupItem->GetTarget()); return $oTopBarAction; } + + //TODO How to handle other types of ApplicationPopupMenuItem? For now, we return null. + return null; } }