Skip to content

Commit

Permalink
[8.x] [Presentation Util] Remove the plugin services toolkit (elastic…
Browse files Browse the repository at this point in the history
…#195502) (elastic#195517)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Presentation Util] Remove the plugin services toolkit
(elastic#195502)](elastic#195502)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Hannah
Mudge","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-08T22:37:18Z","message":"[Presentation
Util] Remove the plugin services toolkit (elastic#195502)\n\nCloses
https://github.com/elastic/kibana/issues/194199\r\n\r\n##
Summary\r\n\r\nNow that no plugins use anything from the
`PresentationUtil` services\r\ntoolkit, it is safe to remove all code
and documentation related to this\r\nfrom the `PresentationUtil`
plugin.\r\n\r\n\r\n### Checklist\r\n\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n\r\n\r\n###
For maintainers\r\n\r\n- [ ] This was checked for breaking API changes
and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"1053493c9c66b881c27d14a600e33a16110b58e3","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Presentation","loe:small","technical
debt","release_note:skip","impact:high","v9.0.0","backport:prev-minor"],"title":"[Presentation
Util] Remove the plugin services
toolkit","number":195502,"url":"https://github.com/elastic/kibana/pull/195502","mergeCommit":{"message":"[Presentation
Util] Remove the plugin services toolkit (elastic#195502)\n\nCloses
https://github.com/elastic/kibana/issues/194199\r\n\r\n##
Summary\r\n\r\nNow that no plugins use anything from the
`PresentationUtil` services\r\ntoolkit, it is safe to remove all code
and documentation related to this\r\nfrom the `PresentationUtil`
plugin.\r\n\r\n\r\n### Checklist\r\n\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n\r\n\r\n###
For maintainers\r\n\r\n- [ ] This was checked for breaking API changes
and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"1053493c9c66b881c27d14a600e33a16110b58e3"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/195502","number":195502,"mergeCommit":{"message":"[Presentation
Util] Remove the plugin services toolkit (elastic#195502)\n\nCloses
https://github.com/elastic/kibana/issues/194199\r\n\r\n##
Summary\r\n\r\nNow that no plugins use anything from the
`PresentationUtil` services\r\ntoolkit, it is safe to remove all code
and documentation related to this\r\nfrom the `PresentationUtil`
plugin.\r\n\r\n\r\n### Checklist\r\n\r\n-
[x]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n\r\n\r\n###
For maintainers\r\n\r\n- [ ] This was checked for breaking API changes
and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"1053493c9c66b881c27d14a600e33a16110b58e3"}}]}]
BACKPORT-->

Co-authored-by: Hannah Mudge <[email protected]>
  • Loading branch information
kibanamachine and Heenawter authored Oct 9, 2024
1 parent 9bdf698 commit 8fdf77d
Show file tree
Hide file tree
Showing 9 changed files with 6 additions and 836 deletions.
206 changes: 6 additions & 200 deletions src/plugins/presentation_util/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,208 +12,12 @@ related: []

The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas).

## Plugin Services Toolkit

While Kibana provides a `useKibana` hook for use in a plugin, the number of services it provides is very large. This presents a set of difficulties:

- a direct dependency upon the Kibana environment;
- a requirement to mock the full Kibana environment when testing or using Storybook;
- a lack of knowledge as to what services are being consumed at any given time.

To mitigate these difficulties, the Presentation Team creates services within the plugin that then consume Kibana-provided (or other) services. This is a toolkit for creating simple services within a plugin.

### Overview

- A `PluginServiceFactory` is a function that will return a set of functions-- which comprise a `Service`-- given a set of parameters.
- A `PluginServiceProvider` is an object that use a factory to start, stop or provide a `Service`.
- A `PluginServiceRegistry` is a collection of providers for a given environment, (e.g. Kibana, Jest, Storybook, stub, etc).
- A `PluginServices` object uses a registry to provide services throughout the plugin.

### Defining Services

To start, a plugin should define a set of services it wants to provide to itself or other plugins.

<DocAccordion buttonContent="Service Definition Example" initialIsOpen>
```ts
export interface PresentationDashboardsService {
findDashboards: (
query: string,
fields: string[]
) => Promise<Array<SimpleSavedObject<DashboardSavedObject>>>;
findDashboardsByTitle: (title: string) => Promise<Array<SimpleSavedObject<DashboardSavedObject>>>;
}

export interface PresentationFooService {
getFoo: () => string;
setFoo: (bar: string) => void;
}

export interface PresentationUtilServices {
dashboards: PresentationDashboardsService;
foo: PresentationFooService;
}
```
</DocAccordion>

This definition will be used in the toolkit to ensure services are complete and as expected.

### Plugin Services

The `PluginServices` class hosts a registry of service providers from which a plugin can access its services. It uses the service definition as a generic.

```ts
export const pluginServices = new PluginServices<PresentationUtilServices>();
```

This can be placed in the `index.ts` file of a `services` directory within your plugin.

Once created, it simply requires a `PluginServiceRegistry` to be started and set.

### Service Provider Registry

Each environment in which components are used requires a `PluginServiceRegistry` to specify how the providers are started. For example, simple stubs of services require no parameters to start, (so the `StartParameters` generic remains unspecified)

<DocAccordion buttonContent="Stubbed Service Registry Example" initialIsOpen>
```ts
export const providers: PluginServiceProviders<PresentationUtilServices> = {
dashboards: new PluginServiceProvider(dashboardsServiceFactory),
foo: new PluginServiceProvider(fooServiceFactory),
};

export const serviceRegistry = new PluginServiceRegistry<PresentationUtilServices>(providers);
```
</DocAccordion>

By contrast, a registry that uses Kibana can provide `KibanaPluginServiceParams` to determine how to start its providers, so the `StartParameters` generic is given:

<DocAccordion buttonContent="Kibana Service Registry Example" initialIsOpen>
```ts
export const providers: PluginServiceProviders<
PresentationUtilServices,
KibanaPluginServiceParams<PresentationUtilPluginStart>
> = {
dashboards: new PluginServiceProvider(dashboardsServiceFactory),
foo: new PluginServiceProvider(fooServiceFactory),
};

export const serviceRegistry = new PluginServiceRegistry<
PresentationUtilServices,
KibanaPluginServiceParams<PresentationUtilPluginStart>
>(providers);
```
</DocAccordion>

### Service Provider

A `PluginServiceProvider` is a container for a Service Factory that is responsible for starting, stopping and providing a service implementation. A Service Provider doesn't change, rather the factory and the relevant `StartParameters` change.

### Service Factories

A Service Factory is nothing more than a function that uses `StartParameters` to return a set of functions that conforms to a portion of the `Services` specification. For each service, a factory is provided for each environment.

Given a service definition:

```ts
export interface PresentationFooService {
getFoo: () => string;
setFoo: (bar: string) => void;
}
```

a factory for a stubbed version might look like this:

```ts
type FooServiceFactory = PluginServiceFactory<PresentationFooService>;

export const fooServiceFactory: FooServiceFactory = () => ({
getFoo: () => 'bar',
setFoo: (bar) => { console.log(`${bar} set!`)},
});
```

and a factory for a Kibana version might look like this:

```ts
export type FooServiceFactory = KibanaPluginServiceFactory<
PresentationFooService,
PresentationUtilPluginStart
>;

export const fooServiceFactory: FooServiceFactory = ({
coreStart,
startPlugins,
}) => {
// ...do something with Kibana services...

return {
getFoo: //...
setFoo: //...
}
}
```

### Using Services

Once your services and providers are defined, and you have at least one set of factories, you can use `PluginServices` to provide the services to your React components:

<DocAccordion buttonContent="Services starting in a plugin" initialIsOpen>
```ts
// plugin.ts
import { pluginServices } from './services';
import { registry } from './services/kibana';

public start(
coreStart: CoreStart,
startPlugins: StartDeps
): Promise<PresentationUtilPluginStart> {
pluginServices.setRegistry(registry.start({ coreStart, startPlugins }));
return {};
}
```
</DocAccordion>

and wrap your root React component with the `PluginServices` context:

<DocAccordion buttonContent="Providing services in a React context" initialIsOpen>
```ts
import { pluginServices } from './services';

const ContextProvider = pluginServices.getContextProvider(),

return(
<I18nContext>
<WhateverElse>
<ContextProvider>{application}</ContextProvider>
</WhateverElse>
</I18nContext>
)
```
</DocAccordion>

and then, consume your services using provided hooks in a component:

<DocAccordion buttonContent="Consuming services in a component" initialIsOpen>
```ts
// component.ts

import { pluginServices } from '../services';

export function MyComponent() {
// Retrieve all context hooks from `PluginServices`, destructuring for the one we're using
const { foo } = pluginServices.getHooks();

// Use the `useContext` hook to access the API.
const { getFoo } = foo.useService();

// ...
}
```
</DocAccordion>

## Redux Embeddables

The Redux Embeddables system allows embeddable authors to interact with their embeddables in a standardized way using Redux toolkit. This wrapper abstracts away store and slice creation, and embeddable input sync. To use this system, a developer can use CreateReduxEmbeddableTools in the constructor of their embeddable, supplying a collection of reducers.

### Reducers

The reducer object expected by the ReduxEmbeddableWrapper is the same type as the reducers expected by [Redux Toolkit's CreateSlice](https://redux-toolkit.js.org/api/createslice).

<DocAccordion buttonContent="Reducers Example" initialIsOpen>
Expand Down Expand Up @@ -247,6 +51,8 @@ From components under the embeddable, actions, containerActions, and the current
// change specialBoolean after 5 seconds
setTimeout(() => embeddableInstance.dispatch.setSpecialBoolean(false), 5000);

}
```
}

```
</DocAccordion>
```
8 changes: 0 additions & 8 deletions src/plugins/presentation_util/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ import { PresentationUtilPlugin } from './plugin';

export type { PresentationLabsService } from './services/presentation_labs_service';

export type {
KibanaPluginServiceFactory,
PluginServiceFactory,
PluginServiceProviders,
KibanaPluginServiceParams,
} from './services/create';
export { PluginServices, PluginServiceProvider, PluginServiceRegistry } from './services/create';

export type { PresentationUtilPluginSetup, PresentationUtilPluginStart } from './types';
export type { SaveModalDashboardProps } from './components/types';

Expand Down

This file was deleted.

Loading

0 comments on commit 8fdf77d

Please sign in to comment.