@@ -146,6 +146,7 @@ export async function buildContextMenuForActions({
146
146
closeMenu = ( ) => { } ,
147
147
} : BuildContextMenuParams ) : Promise < EuiContextMenuPanelDescriptor [ ] > {
148
148
const panels : Record < string , PanelDescriptor > = {
149
+ // This is the first panel which links out to all others via items property
149
150
mainMenu : {
150
151
id : 'mainMenu' ,
151
152
title,
@@ -157,35 +158,51 @@ export async function buildContextMenuForActions({
157
158
const context : ActionExecutionContext < object > = { ...item . context , trigger : item . trigger } ;
158
159
const isCompatible = await item . action . isCompatible ( context ) ;
159
160
if ( ! isCompatible ) return ;
160
- let parentPanel = '' ;
161
- let currentPanel = '' ;
161
+
162
+ // Reference to the last/parent/upper group.
163
+ // Groups are provided in order of parent to children.
164
+ let parentGroupId = '' ;
165
+
162
166
if ( action . grouping ) {
163
167
for ( let i = 0 ; i < action . grouping . length ; i ++ ) {
164
168
const group = action . grouping [ i ] ;
165
- currentPanel = group . id ;
166
- if ( ! panels [ currentPanel ] ) {
169
+ const groupId = group . id ;
170
+
171
+ // If a panel does not exist for the current group, then create it
172
+ if ( ! panels [ groupId ] ) {
167
173
const name = group . getDisplayName ? group . getDisplayName ( context ) : group . id ;
168
- panels [ currentPanel ] = {
169
- id : currentPanel ,
174
+
175
+ // Create panel for group
176
+ panels [ groupId ] = {
177
+ id : groupId ,
170
178
title : name ,
171
179
items : [ ] ,
172
180
_level : i ,
173
181
_icon : group . getIconType ? group . getIconType ( context ) : 'empty' ,
174
182
} ;
175
- if ( parentPanel ) {
176
- panels [ parentPanel ] . items ! . push ( {
183
+
184
+ // If there are multiple groups and this is not the first group,
185
+ // then add an item to the parent group relating to this group
186
+ if ( parentGroupId ) {
187
+ panels [ parentGroupId ] . items ! . push ( {
177
188
name,
178
- panel : currentPanel ,
189
+ panel : groupId ,
179
190
icon : group . getIconType ? group . getIconType ( context ) : 'empty' ,
180
191
_order : group . order || 0 ,
181
192
_title : group . getDisplayName ? group . getDisplayName ( context ) : '' ,
182
193
} ) ;
183
194
}
184
195
}
185
- parentPanel = currentPanel ;
196
+
197
+ // Save the current group, because it will be used as the parent group
198
+ // for adding items to it for any additional groups in the array
199
+ parentGroupId = groupId ;
186
200
}
187
201
}
188
- panels [ parentPanel || 'mainMenu' ] . items ! . push ( {
202
+
203
+ // Add a context menu item for this action so it shows up on a context menu panel.
204
+ // We add this within the parent group or default to the mainMenu panel.
205
+ panels [ parentGroupId || 'mainMenu' ] . items ! . push ( {
189
206
name : action . MenuItem
190
207
? React . createElement ( uiToReactComponent ( action . MenuItem ) , { context } )
191
208
: action . getDisplayName ( context ) ,
@@ -197,8 +214,10 @@ export async function buildContextMenuForActions({
197
214
_title : action . getDisplayName ( context ) ,
198
215
} ) ;
199
216
} ) ;
217
+
200
218
await Promise . all ( promises ) ;
201
219
220
+ // For each panel, sort items by order and title
202
221
for ( const panel of Object . values ( panels ) ) {
203
222
const items = panel . items . filter ( Boolean ) as ItemDescriptor [ ] ;
204
223
panel . items = _ . sortBy (
@@ -208,13 +227,23 @@ export async function buildContextMenuForActions({
208
227
) ;
209
228
}
210
229
230
+ // On the mainMenu, before adding in items for other groups, the first 4 items are shown.
231
+ // Any additional items are hidden behind a "more" item
211
232
wrapMainPanelItemsIntoSubmenu ( panels , 'mainMenu' ) ;
212
233
213
234
for ( const panel of Object . values ( panels ) ) {
235
+ // If the panel is a root-level panel, such as the parent of a group,
236
+ // then create mainMenu item for this panel
214
237
if ( panel . _level === 0 ) {
215
- // TODO: Add separator line here once it is available in EUI.
216
- // See https://github.com/elastic/eui/pull/4018
217
- if ( panel . items . length > 3 ) {
238
+ // Add separator with unique key if needed
239
+ if ( panels . mainMenu . items . length ) {
240
+ panels . mainMenu . items . push ( { isSeparator : true , key : `${ panel . id } separator` } ) ;
241
+ }
242
+
243
+ // If a panel has more than one child, then allow items to be grouped
244
+ // and link to it in the mainMenu. Otherwise, flatten the group.
245
+ // Note: this only happens on the root level panels, not for inner groups.
246
+ if ( panel . items . length > 1 ) {
218
247
panels . mainMenu . items . push ( {
219
248
name : panel . title || panel . id ,
220
249
icon : panel . _icon || 'empty' ,
0 commit comments