You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Management is one of the four primary "domains" covered by @elastic/kibana-app-arch (along with Data, Embeddables, and Visualizations). There are two main purposes for this service:
Own the management "framework" -- the UI that displays the management sidebar nav, the landing page, and handles rendering each of the sections
Expose a registry for other plugins to add their own registry sections to the UI and add nested links to them in the sidebar.
Purpose
The purpose of this discussion is to consider item 2 above -- the service for registering sections to the nav & loading them up. Below is a proposed design for how this would look in the new platform. The reason for having this discussion now is because some plugins will be blocked on fully moving to the new platform by the management plugin.
Design Goals
Remove another usage of IndexedArray & uiRegistry (required for migration)
Remove dependency on ui/routes (required for migration)
Remove management section uiExport (required for migration)
Simple API that is designed in keeping with new platform principles
This includes being rendering-framework-agnostic... You should be able to build your management section UI however you'd like
Clear separation of app/UI code and service code, even if both live within the same plugin
Flexibility to potentially support alternate layouts in the future (see mockups in reference section below)
// myplugin/indexnewKibana.Plugin({uiExports: {managementSections: ['myplugin/management'],}});// myplugin/public/managementimport{management}from'ui/management';// completely new sectionconstnewSection=management.register('mypluginsection',{name: 'mypluginsection',order: 10,display: 'My Plugin',icon: 'iconName',});newSection.register('mypluginlink',{name: 'mypluginlink',order: 10,display: 'My sublink',url: `#/management/myplugin`,});// new link in existing sectionconstkibanaSection=management.getSection('kibana');kibanaSection.register('mypluginlink',{name: 'mypluginlink',order: 10,display: 'My sublink',url: `#/management/myplugin`,});// use ui/routes to render componentimportroutesfrom'ui/routes';constrenderReact=(elem)=>{render(<MyApp/>,elem);};routes.when('management/myplugin',{controller($scope,$http,kbnUrl){$scope.$on('$destroy',()=>{constelem=document.getElementById('usersReactRoot');if(elem)unmountComponentAtNode(elem);});$scope.$$postDigest(()=>{constelem=document.getElementById('usersReactRoot');constchangeUrl=(url)=>{kbnUrl.change(url);$scope.$apply();};renderReact(elem,$http,changeUrl);});},});
Current public contracts owned by the legacy service:
// ui/management/indexinterfaceAPI{
PAGE_TITLE_COMPONENT: string;// actually related to advanced settings?
PAGE_SUBTITLE_COMPONENT: string;// actually related to advanced settings?
PAGE_FOOTER_COMPONENT: string;// actually related to advanced settings?
SidebarNav: React.SFC<any>;
registerSettingsComponent: (id: string,component: string|React.SFC<any>,allowOverride: boolean)=>void;
management: newManagementSection();
MANAGEMENT_BREADCRUMB: {
text: string;
href: string;};}// ui/management/sectionclassManagementSection{getvisibleItems,addListener: (fn: function)=>void,register: (id: string,options: Options)=>ManagementSection|Error,deregister: (id: string)=>void,hasItem: (id: string)=>boolean,getSection: (id: string)=>ManagementSection,hide: ()=>void,show: ()=>void,disable: ()=>void,enable: ()=>void,}interfaceOptions{order: number|null;display: string|null;// defaults to idurl: string|null;// defaults to ''visible: boolean|null;// defaults to truedisabled: boolean|null;// defaults to falsetooltip: string|null;// defaults to ''icon: string|null;// defaults to ''}
Proposed API
This API is influenced heavily by the design of Core's application service mounting. The intent is to make the experience consistent with that service; the Management section is basically one big app with a bunch of registered "subapps".
Example usage:
// my_plugin/public/plugin.tsexportclassMyPlugin{setup(core,{ management }){management.sections.register({id: 'my-section',title: 'My Main Section',// display namedescription: 'hello',// not used in current UI, but possibly in futureorder: 10,euiIconType: 'iconName',});management.sections.registerLink('my-section',{id: 'my-link',title: 'My Link',// display namedescription: 'hello',// not used in current UI, but possibly in futureorder: 20,asyncmount(context,params){const{ renderApp }=awaitimport('./my-section');returnrenderApp(context,params);}});}}// my_plugin/public/my-section.tsxexportfunctionrenderApp(context,{ basePath, element }){ReactDOM.render(// `basePath` would be `/app/management/my-section/my-link`<MyAppbasename={basePath}/>,element);// return value must be a function that unmounts (just like Core Application Service)return()=>ReactDOM.unmountComponentAtNode(element);}
Detailed design:
interfaceManagementSetup{sections: SectionsService;}interfaceSectionsService{register: Register;registerLink: RegisterLink;getAvailable: ()=>Section[];// filtered based on capabilitiesget: (id: string)=>Section|undefined;getLink: (id: string)=>Link|undefined;}typeRegister=({id: string;title: string;description: string;// not used in current UI, but possibly in futureorder?: number;euiIconType?: string;// takes precedence over `icon` property.icon?: string;// URL to image file; fallback if no `euiIconType`})=>Section|Error;typeRegisterLink=(sectionId: string,{id: string;title: string;description: string;// not used in current UI, but possibly in futureorder?: number;
mount: ManagementSectionMount;})=>Link|Error;typeUnmount=()=>Promise<void>|void;typeManagementSectionMount=(context: AppMountContext,// provided by core.ApplicationServiceparams: MountParams,)=>Unmount|Promise<Unmount>;interfaceMountParams{basePath: string;// base path for setting up your routerelement: HTMLElement;// element the section should render into}interfaceSection{id: string;title: string;description: string;baseBath: string;links: Link[];order?: number;euiIconType?: string;icon?: string;destroy: ()=>Promise<void>|void;// de-registers and destroys all links}interfaceLink{id: string;title: string;description: string;basePath: string;sectionId: string;order?: number;destroy: ()=>Promise<void>|void;// de-registers & calls unmount()}
Caveats, Questions, & Discussion Points:
This removes the ability to infinitely nest sections within each other by making a distinction between a section header and a nav link.
So far we didn't seem to be using this feature anyway, but would like feedback on any use cases for it.
The hide/show/disable/enable options were dropped with the assumption that we will be working with uiCapabilities to determine this instead... so people shouldn't need to manage it manually as they can look up a pre-filtered list of sections.
This was updated to add flexibility for custom (non-EUI) icons as outlined in Allow custom icons for management sections #32661. Much like the Core Application Service, you either choose an EUI icon, or provide a URL to an icon.
Do individual links within a section need the ability to specify icons? Currently only the section headers have icons.
Added field for a description, though this isn't currently used in the UI.
Next Steps
We will keep this issue open for feedback for one week (until August 23, 2019), at which point we will seek any final comments before closing the discussion in order to make plans for future implementation.
Copying a few folks here who either have knowledge of the legacy management framework, or who are actively managing plugins that register management sections:
Background
Management is one of the four primary "domains" covered by @elastic/kibana-app-arch (along with Data, Embeddables, and Visualizations). There are two main purposes for this service:
Purpose
The purpose of this discussion is to consider item 2 above -- the service for registering sections to the nav & loading them up. Below is a proposed design for how this would look in the new platform. The reason for having this discussion now is because some plugins will be blocked on fully moving to the new platform by the management plugin.
Design Goals
Reference
Overview of the legacy service
Example usage of how this looks today:
Current public contracts owned by the legacy service:
Proposed API
This API is influenced heavily by the design of Core's application service mounting. The intent is to make the experience consistent with that service; the Management section is basically one big app with a bunch of registered "subapps".
Example usage:
Detailed design:
Caveats, Questions, & Discussion Points:
Next Steps
We will keep this issue open for feedback for one week (until August 23, 2019), at which point we will seek any final comments before closing the discussion in order to make plans for future implementation.
Copying a few folks here who either have knowledge of the legacy management framework, or who are actively managing plugins that register management sections:
@bmcconaghy @cjcenizal @jen-huang @mattkime @kobelb @legrego @alvarezmelissa87 @peteharverson @mattapperson @stacey-gammon