import { injectable } from '@cloudbeaver/core-di' ; import { ActionService } from '../Action/ActionService' ; import { isAction } from '../Action/createAction' ; import type { IAction } from '../Action/IAction' ; import type { IDataContextProvider } from '../DataContext/IDataContextProvider' ; import { isMenu } from './createMenu' ; import type { IMenuHandler } from './IMenuHandler' ; import type { IMenuItemsCreator , MenuCreatorItem } from './IMenuItemsCreator' ; import type { IMenuActionItem } from './MenuItem/IMenuActionItem' ; import type { IMenuItem } from './MenuItem/IMenuItem' ; import { MenuActionItem } from './MenuItem/MenuActionItem' ; import { MenuSubMenuItem } from './MenuItem/MenuSubMenuItem' ; @ injectable ( ) export class MenuService { private handlers : Map < string , IMenuHandler > ; private creators : IMenuItemsCreator [ ] ; constructor ( private readonly actionService ) { this . creators = [ ] ; this . handlers = new Map ( ) ; } createActionItem ( context , action ) { const actionItem = this . actionService . getAction ( context , action ) ; if ( actionItem ) { return new MenuActionItem ( actionItem ) ; } return null ; } isMenuAvailable ( context ) { return this . creators . some ( filterApplicable ( context ) ) ; } addCreator ( creator ) { this . creators . push ( creator ) ; } setHandler ( handler ) { if ( this . handlers . has ( handler . id ) ) { throw new Error ( `Menu handler with same id (${ handler . id }) already exists` ) ; } this . handlers . set ( handler . id , handler ) ; } getHandler ( context ) { for ( const handler of this . handlers . values ( ) ) { if ( handler . isApplicable ( context ) ) { return handler ; } } return null ; } getMenu ( context ) { const applicableCreators = this . creators . filter ( filterApplicable ( context ) ) ; return applicableCreators . reduce < MenuCreatorItem [ ] > ( ( items , creator ) => { if ( creator . orderItems ) { return creator . orderItems ( context , items ) ; } return items ; } , applicableCreators . reduce < MenuCreatorItem [ ] > ( ( items , creator ) => creator . getItems ( context , items ) , [ ] ) . filter ( item => { if ( isAction ( item ) ) { return this . actionService . getHandler ( context , item ) !== null ; } return true ; } ) ) . map ( item => { if ( isAction ( item ) ) { return this . createActionItem ( context , item ) as IMenuItem ; } if ( isMenu ( item ) ) { return new MenuSubMenuItem ( item ) as IMenuItem ; } return item ; } ) . filter ( Boolean ) ; } } function filterApplicable ( context ) { return ( creator ) => creator . isApplicable ?. ( context ) ?? true ; }