55 chevronRightIcon ,
66 closeIcon ,
77 gitPullRequestIcon ,
8+ moreHorizontalIcon ,
89 plusIcon ,
910 runningStatusIcon ,
1011 searchIcon ,
@@ -251,62 +252,11 @@ export function mountProjectsPane(root: HTMLElement, store: AppStore, api: ApiCl
251252 settingsBtn . addEventListener ( 'click' , ( ) => {
252253 openSettingsDialog ( )
253254 } )
254- const menuButton = el (
255- 'button' ,
256- {
257- type : 'button' ,
258- class : 'projects-menu-btn' ,
259- 'aria-label' : 'Project menu' ,
260- 'aria-haspopup' : 'menu' ,
261- 'data-tooltip' : 'Settings and automations' ,
262- } ,
263- settingsIcon ( ) ,
264- )
265- menuButton . addEventListener ( 'click' , ( ) => {
266- menuButton . disabled = true
267- void api . plugins
268- . list ( )
269- . then ( ( result ) => {
270- const rect = menuButton . getBoundingClientRect ( )
271- const plugin = result . plugins . find ( hasAutomationDialog )
272- showContextMenu ( rect . left , rect . top , [
273- {
274- label : 'Settings' ,
275- onSelect : ( ) : void => {
276- openSettingsDialog ( )
277- } ,
278- } ,
279- ...( plugin
280- ? [
281- {
282- label : 'Automations' ,
283- onSelect : ( ) : void => {
284- openAutomationDialog ( store , api )
285- } ,
286- } ,
287- {
288- label : 'New automation…' ,
289- disabled : ! store . getState ( ) . activeProjectId ,
290- onSelect : ( ) : void => {
291- openAutomationDialog ( store , api , { createNew : true } )
292- } ,
293- } ,
294- ]
295- : [ ] ) ,
296- ] )
297- } )
298- . catch ( ( error : unknown ) => {
299- showErrorToast ( 'Could not load project menu' , error )
300- } )
301- . finally ( ( ) => {
302- menuButton . disabled = false
303- } )
304- } )
305255 root . append (
306256 header ,
307257 searchRow ,
308258 list ,
309- el ( 'div' , { class : 'projects-settings-actions' } , menuButton , settingsBtn ) ,
259+ el ( 'div' , { class : 'projects-settings-actions' } , settingsBtn ) ,
310260 )
311261
312262 let sshWorkspaceEnabled = false
@@ -889,27 +839,74 @@ export function mountProjectsPane(root: HTMLElement, store: AppStore, api: ApiCl
889839 }
890840 switchProject ( store , api , project . id )
891841 } )
842+ const projectMenuEntries : ContextMenuEntry [ ] = [
843+ {
844+ label : 'Remove from sidebar' ,
845+ onSelect : ( ) : void => {
846+ void removeProject ( store , api , project . id )
847+ } ,
848+ } ,
849+ ...groupMenuEntries ( project , projectGroups ) ,
850+ ]
892851 projectRow . addEventListener ( 'contextmenu' , ( e ) => {
893852 e . preventDefault ( )
894853 e . stopPropagation ( )
895- showContextMenu ( e . clientX , e . clientY , [
896- {
897- label : 'Remove from sidebar' ,
898- onSelect : ( ) : void => {
899- void removeProject ( store , api , project . id )
900- } ,
901- } ,
902- ...groupMenuEntries ( project , projectGroups ) ,
903- ] )
854+ showContextMenu ( e . clientX , e . clientY , projectMenuEntries )
855+ } )
856+ const menuButton = el (
857+ 'button' ,
858+ {
859+ type : 'button' ,
860+ class : 'project-menu-btn' ,
861+ 'aria-label' : `Project menu for ${ projectDisplayName ( project ) } ` ,
862+ 'aria-haspopup' : 'menu' ,
863+ 'data-tooltip' : 'Project menu' ,
864+ } ,
865+ moreHorizontalIcon ( 'ui-icon ui-icon-sm' ) ,
866+ )
867+ menuButton . addEventListener ( 'click' , ( ) => {
868+ menuButton . disabled = true
869+ void api . plugins
870+ . list ( )
871+ . then ( ( result ) => {
872+ if ( ! menuButton . isConnected ) return
873+ const rect = menuButton . getBoundingClientRect ( )
874+ const entries : ContextMenuEntry [ ] = [ ]
875+ if ( result . plugins . some ( hasAutomationDialog ) ) {
876+ entries . push (
877+ {
878+ label : 'Automations' ,
879+ onSelect : ( ) : void => {
880+ openAutomationDialog ( store , api , { projectId : project . id } )
881+ } ,
882+ } ,
883+ {
884+ label : 'New automation…' ,
885+ disabled : project . missing === true ,
886+ onSelect : ( ) : void => {
887+ openAutomationDialog ( store , api , { projectId : project . id , createNew : true } )
888+ } ,
889+ } ,
890+ )
891+ }
892+ showContextMenu ( rect . left , rect . bottom , [ ...entries , ...projectMenuEntries ] )
893+ } )
894+ . catch ( ( error : unknown ) => {
895+ showErrorToast ( 'Could not load project menu' , error )
896+ } )
897+ . finally ( ( ) => {
898+ menuButton . disabled = false
899+ } )
904900 } )
901+ const projectLine = el ( 'div' , { class : 'project-line' } , projectRow , menuButton )
902+ entry . append ( projectLine )
905903
906904 if ( isExpanded && project . missing ) {
907- entry . append ( projectRow , renderMissingNotice ( project ) )
905+ entry . append ( renderMissingNotice ( project ) )
908906 return entry
909907 }
910908
911909 if ( isExpanded ) {
912- const projectLine = el ( 'div' , { class : 'project-line' } )
913910 const newThreadBtn = el (
914911 'button' ,
915912 {
@@ -932,10 +929,7 @@ export function mountProjectsPane(root: HTMLElement, store: AppStore, api: ApiCl
932929 }
933930 openNewThread ( store )
934931 } )
935- projectLine . append ( projectRow , newThreadBtn )
936- entry . append ( projectLine )
937- } else {
938- entry . append ( projectRow )
932+ projectLine . append ( newThreadBtn )
939933 }
940934
941935 if ( ! isExpanded ) return entry
0 commit comments