N°9152 - Add extensibility API endpoints for UI elements - #1017
N°9152 - Add extensibility API endpoints for UI elements#1017steffunky wants to merge 3 commits into
Conversation
…. API endpoints are working and displaying in the UI
There was a problem hiding this comment.
Pull request overview
Adds extension API endpoints for top-bar, field, case-log, and activity-panel actions.
Changes:
- Adds new popup-menu extension constants and UI action factories.
- Renders extension actions across object-detail interfaces.
- Adds supporting JavaScript, templates, styles, and autoload mappings.
Reviewed changes
Copilot reviewed 43 out of 44 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-url.js.twig |
Adds URL-action JS template. |
templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-url.html.twig |
Renders top-bar URL actions. |
templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.js.twig |
Handles top-bar JS actions. |
templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.html.twig |
Renders top-bar JS actions. |
templates/base/layouts/top-bar/top-bar-quick-action/layout.html.twig |
Adds abstract action template. |
templates/base/layouts/top-bar/layout.html.twig |
Renders top-bar extension actions. |
templates/base/layouts/activity-panel/layout.html.twig |
Renders activity-panel actions. |
templates/base/layouts/activity-panel/activity-action/activity-action-url.js.twig |
Adds URL-action JS placeholder. |
templates/base/layouts/activity-panel/activity-action/activity-action-url.html.twig |
Renders activity URL actions. |
templates/base/layouts/activity-panel/activity-action/activity-action-js.js.twig |
Adds JS-action JS placeholder. |
templates/base/layouts/activity-panel/activity-action/activity-action-js.html.twig |
Renders activity JS actions. |
templates/base/components/field/layout.html.twig |
Renders field actions and value. |
sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionURL.php |
Defines URL quick actions. |
sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionJS.php |
Defines JS quick actions. |
sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickActionFactory.php |
Converts popup items to quick actions. |
sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickAction.php |
Defines the quick-action base class. |
sources/Application/UI/Base/Layout/TopBar/TopBarFactory.php |
Collects top-bar extension actions. |
sources/Application/UI/Base/Layout/TopBar/TopBar.php |
Stores top-bar actions. |
sources/Application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryFormFactory.php |
Adds case-log field actions. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelFactory.php |
Collects activity-panel actions. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionURL.php |
Defines activity URL actions. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionJS.php |
Defines activity JS actions. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelActionFactory.php |
Groups and converts activity actions. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelAction.php |
Defines the activity-action base. |
sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanel.php |
Stores activity actions. |
sources/Application/UI/Base/Component/Field/FieldUIBlockFactory.php |
Builds field action buttons and menus. |
sources/Application/UI/Base/Component/Field/Field.php |
Adds field values and actions. |
sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php |
Converts popup items into buttons. |
sources/Application/UI/Base/Common/Action/tActionURL.php |
Adds shared URL-action behavior. |
sources/Application/UI/Base/Common/Action/tActionJs.php |
Adds shared JS-action behavior. |
sources/Application/UI/Base/Common/Action/tActionCommon.php |
Adds shared action metadata. |
lib/composer/autoload_static.php |
Registers new classes and traits. |
lib/composer/autoload_classmap.php |
Updates generated class mappings. |
js/layouts/activity-panel/activity-panel.js |
Dispatches actions by active tab. |
css/backoffice/layout/top-bar/_top-bar.scss |
Defines top-bar styling. |
css/backoffice/layout/top-bar/_top-bar-action.scss |
Styles top-bar actions. |
css/backoffice/layout/top-bar/_all.scss |
Aggregates top-bar styles. |
css/backoffice/layout/activity-panel/_all.scss |
Imports activity-action styles. |
css/backoffice/layout/activity-panel/_activity-action.scss |
Styles activity-panel actions. |
css/backoffice/layout/_all.scss |
Updates layout imports. |
css/backoffice/components/_field.scss |
Styles field action buttons. |
application/cmdbabstract.class.inc.php |
Collects per-field extension actions. |
application/applicationextension/backoffice/iPopupMenuExtension.php |
Declares new extension endpoints. |
application/applicationextension/backoffice/ApplicationPopupMenuItem.php |
Adds popup-item label mutation. |
Suppressed comments (2)
sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php:429
- This JS popup-item conversion copies the click code but drops
GetLinkedScripts(). Case-log actions using the API's optional script dependencies will therefore execute without their required libraries. Register each linked script on the returned button, as the existing popup-menu rendering path does.
$oButton->SetOnClickJsCode($oPopupItem->GetJsCode());
return $oButton;
sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php:400
- The popup-item label is mandatory but its tooltip is optional and defaults to an empty string. This icon-only link passes only the optional tooltip, so the generated control has no accessible name when no tooltip was set. Fall back to
GetLabel()when the tooltip is empty.
$oButton = self::MakeIconLink(
$oPopupItem->GetIconClass(),
$oPopupItem->GetTooltip(),
$oPopupItem->GetURL(),
$oPopupItem->GetTarget(),
);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| /** @var \iPopupMenuExtension $oExtensionInstance */ | ||
| foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) { | ||
| foreach ($oExtensionInstance::EnumItems(iPopupMenuExtension::MENU_TOPBAR_ACTIONS, []) as $oMenuItem) { |
| $oActionButton = ButtonUIBlockFactory::MakeIconButtonFromApplicationPopupMenuItem($oAction); | ||
| $oActionButton->AddCSSClass('ibo-field--action'); |
| $oButton = self::MakeIconAction( | ||
| $oPopupItem->GetIconClass(), | ||
| $oPopupItem->GetTooltip() | ||
| ); |
| aria-label="{{ oUIBlock.GetTooltip() }}" | ||
| data-tooltip-content="{{ oUIBlock.GetTooltip() }}" |
| {% if oUIBlock.GetTooltip() is not empty %} | ||
| data-tooltip-content="{{ oUIBlock.GetTooltip() }}" | ||
| aria-label="{{ oUIBlock.GetTooltip() }}" | ||
| {% endif %} |
| {% if oUIBlock.GetTooltip() is not empty %} | ||
| data-tooltip-content="{{ oUIBlock.GetTooltip() }}" | ||
| aria-label="{{ oUIBlock.GetTooltip() }}" | ||
| {% endif %} |
| $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'); |
bdalsass
left a comment
There was a problem hiding this comment.
Great 🚀
Missing some parameters and return type, maybe you can add static return type when returning $this on traits.
| } | ||
|
|
||
| .ibo-field--action { | ||
| padding: 3px 6px; |
There was a problem hiding this comment.
Could be replaced with scss vars 🫣
There was a problem hiding this comment.
Could be pair-programmed with you 😉
Molkobain
left a comment
There was a problem hiding this comment.
Some things to discuss, but very good job overall 🙌
| } | ||
|
|
||
| .ibo-caselog-entry-form--action-buttons--extra-actions .ibo-button-separator{ | ||
| vertical-align: center ; |
There was a problem hiding this comment.
Can't you use flex align-items instead?
| * @api | ||
| * @since 3.3.0 | ||
| */ | ||
| public function SetLabel($sLabel) |
There was a problem hiding this comment.
| public function SetLabel($sLabel) | |
| public function SetLabel(string $sLabel) : void |
The rest of the API isn't typed because it has to be backward compatible, but it would hurt to type new methods IMO.
|
|
||
| /** | ||
| * Get the list of items to be added to the backoffice top-bar items | ||
| * $param is null for now, in a distant future we want to give a complete context |
There was a problem hiding this comment.
| * $param is null for now, in a distant future we want to give a complete context | |
| * $param is null for now, in a distant future we want to give a complete context | |
| * @since 3.3.0 |
| 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 => attribute code , mode => edit/read] |
There was a problem hiding this comment.
| * $param is an array: ['object' => DBObject, att_code => attribute code , mode => edit/read] | |
| * $param is an array: ['object' => DBObject, att_code => attribute code , mode => edit/read] | |
| * @since 3.3.0 |
| 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_att_code => caselog attribute code or 'activity'] |
There was a problem hiding this comment.
| * $param = ['object' => DBObject, caselog_att_code => caselog attribute code or 'activity'] | |
| * $param = ['object' => DBObject, caselog_att_code => caselog attribute code or 'activity'] | |
| * @since 3.3.0 |
| } | ||
|
|
||
| // Add object arrays | ||
| $aSubBlocksNames = ['Actions']; |
There was a problem hiding this comment.
Shouldn't we rename all the following from "actions" to "quick actions" to match UIBlocks / SCSS?
| } | ||
|
|
||
| /** @var \iPopupMenuExtension $oExtensionInstance */ | ||
| foreach (MetaModel::EnumPlugins('iPopupMenuExtension') as $oExtensionInstance) { |
There was a problem hiding this comment.
Same comment as above about InterfaceDiscovery.
There was a problem hiding this comment.
When is that supposed to be called? I thought there should be no separator between (round) buttons on the activity panel.
There was a problem hiding this comment.
If no needed, can't we just delete it and remove the reference in the PHP class?
There was a problem hiding this comment.
IMO you should factorize most of the markup here instead of in the JS / URL children templates as there is a lot in common. And set TWIG blocks in it so you just have to overload these in the children templates.
Base information
Symptom (bug) / Objective (enhancement)
With upcoming AI extensions and in order to remove a lot of UI hacks from iTop extensions, we need to add endpoints to iTop core in order to place buttons or actions in the main part of UI elements.
There's already a good number of endpoints in
iPopupMenuExtensionbut we still need to do some JS hacks for more complex elements added in iTop 3.0Proposed solution (bug and enhancement)
This PR adds new endpoints for
iPopupMenuExtensionand provides UIBlock factories a way to build elements withApplicationPopupMenuItemobjects.MENU_TOPBAR_ACTIONS(red) allows to add actions in the top barMENU_OBJDETAILS_FIELD_ACTIONS(purple) allows to add actions next to attributes, in read/write and includes caselogsMENU_OBJDETAILS_ACTIVITY_PANEL_ACTIONS(green) allows to add action to the activity panel on read and can be filtered on caselog attribute or activity tab itself.Checklist before requesting a review