1 | # Jenkins JavaScript Extensions
|
2 |
|
3 | Jenkins JavaScript Extensions are extensions which contribute to the UI in Jenkins BlueOcean.
|
4 | This module is used to define extension points - locations where the application accepts plugin-provided implementations.
|
5 | This module is also used to process the plugin extension point implementations to provide to BlueOcean.
|
6 |
|
7 | This module is published via npm as `@jenkins-cd/js-extensions` so that other plugins, external to the blueocean project, can make use of it.
|
8 | Plugins can themselves make use of extension points.
|
9 |
|
10 | Jenkins JavaScript Extensions are based on the extensibility model already established by Jenkins, based on data and views, with the ability to inherit views based on parent data types.
|
11 |
|
12 | Jenkins JavaScript Extensions: `@jenkins-cd/js-extensions` module exports:
|
13 | - `Renderer` - a React component to conveniently render extensions
|
14 | - `store` - the `ExtensionStore` instance (which must be initialized before it can be used)
|
15 | - `classMetadataStore` - class/capability metadata store
|
16 | - `dataType()` - function for filtering extensions based on the data type
|
17 | - `componentType()` - function for filtering extensions based on the required component type (e.g. React class)
|
18 |
|
19 | ### ExtensionStore API
|
20 |
|
21 | The `ExtensionStore` API is very simple, all public methods are asynchronous:
|
22 |
|
23 | - `getExtensions(extensionPointName, [filter,] onload)`
|
24 | This method will async load data, filter the extensions based on the provided `filter`s, and call the onload handler with a list of extension exports, e.g. the React classes or otherwise exported references.
|
25 | `filter` - a filter function currently the module exports the following functions - see the exported functions for the commonly used filters
|
26 |
|
27 | ### ClassMetadataStore API
|
28 |
|
29 | - `getClassMetadata(dataType, onload)`
|
30 | This will return a list of type information, from the [classes API](../blueocean-rest/README.md#classes_API), this method also handles caching results locally.
|
31 |
|
32 | ### Rendering extension points
|
33 |
|
34 | The most common usage pattern is to use the exported `Renderer`, specifying the extension point name, any necessary contextual data, and optionally specifying a data type.
|
35 |
|
36 | import Extensions from '@jenkins-cd/js-extensions';
|
37 | ...
|
38 | <Extensions.Renderer extensionPoint="jenkins.navigation.top.menu" />
|
39 |
|
40 | For example, rendering the test results for a build may be scoped to the specific type of test results in this manner:
|
41 |
|
42 | <Extensions.Renderer extensionPoint="test-results-view" filter={dataType(data)} testResults={data} />
|
43 |
|
44 | The `ExtensionRenderer` component optionally uses the [classes API](../blueocean-rest/README.md#classes_API) to look up an appropriate, specific set of views for the data being displayed.
|
45 | This should works seamlessly with other [capabilities](../blueocean-rest/README.md#capabilities).
|
46 |
|
47 |
|
48 | ### Defining extension point implementations
|
49 |
|
50 | Extensions are defined in a `jenkins-js-extensions.yaml` file in the javascript source directory of a plugin by defining a list of extensions similar to this:
|
51 |
|
52 | # Extensions in this plugin
|
53 | extensions:
|
54 | - component: AboutNavLink
|
55 | extensionPoint: jenkins.topNavigation.menu
|
56 | - component: components/tests/AbstractTestResult
|
57 | extensionPoint: jenkins.test.result
|
58 | dataType: hudson.tasks.test.AbstractTestResultAction
|
59 |
|
60 | Properties are:
|
61 | - `component`: a module from which the default export will be used
|
62 | - `extensionPoint`: the extension point name
|
63 | - `dataType`: an optional Java data type this extension handles
|
64 |
|
65 | For example, the `AboutNavLink` might be defined as a default export:
|
66 |
|
67 | export default class NavLink extends React.Component {
|
68 | ...
|
69 | }
|
70 |
|
71 | #### Enforcing specific component types
|
72 |
|
73 | In order to ensure a specific component is returned, an extension point may also use the `componentType` filter - it accepts an object prototype (e.g. an ES6 class), e.g.:
|
74 |
|
75 | import TestResults from './base-components/TestResults';
|
76 | ...
|
77 | <Extensions.Renderer extensionPoint="test-view" filter={componentType(TestResults)} ... />
|
78 |
|
79 | Extensions are not limited to React components.
|
80 | The `componentType` filter will attempt to match returned components by a series of prototype and typeof checks to appropriately filter returned types including ES6 classes.
|
81 |
|
82 | ### i18n resource pre-loading
|
83 |
|
84 | By default, all `@jenkins-cd/js-extensions` generated JavaScript bundles will automatically preload the i18n resource bundles it finds in the
|
85 | `src/main/resources/jenkins/plugins/[pluginId]`, where `pluginId` is the Jenkins HPI plugin ID with all hyphen characters replaced by a path separator
|
86 | e.g. for `blueocean-dashboard`, the path that is searched is `src/main/resources/jenkins/plugins/blueocean/dashboard`.
|
87 |
|
88 | > See `findI18nBundles()` in [@jenkins-cd/subs/extensions-bundle.js](@jenkins-cd/subs/extensions-bundle.js)
|
89 |
|
90 | In some situations, a `@jenkins-cd/js-extensions` generated bundle may depend on i18n resources that are not in the default location or not in the host plugin (e.g. they may be defined in a "common" style utility plugin). In this situation,
|
91 | your plugin needs to know about these i18n resources in order to generate the right pre-loading code into the generated bundle. To tell `@jenkins-cd/js-extensions` about the resources in the other plugin, you need to manually define a `i18nBundles`
|
92 | list in the `jenkins-js-extensions.yaml` e.g.
|
93 |
|
94 | ```yaml
|
95 | extensions:
|
96 | # etc ....
|
97 |
|
98 | i18nBundles:
|
99 | - jenkins.plugins.aaa.Messages
|
100 | - hpiPluginId: acme-commons
|
101 | resource: jenkins.plugins.acme.commons.Messages
|
102 | ```
|
103 |
|
104 | > Note how `i18nBundles` entries can define a string or an object, allowing the loading of bundles from plugins other than the default (i.e. the same plugin as the `@jenkins-cd/js-extensions` generated JavaScript bundle).
|
105 |
|