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
chore(docs): fill in some missing documentation (#1852)
This change adds documentation for a few changes to the frontendi application
that have been available, namely the ability to add additional custom context
menu items to the entity page from a dynamic plugin, the ability to supply a
custom sidebar item component from a dynamic plugin and finally the
changes related to how API factories can be discovered from a frontend
dynamic plugin if it exports it's plugin object vs. the need to
explicitly configure frontend API factories.
Signed-off-by: Stan Lewis <gashcrumb@gmail.com>
Copy file name to clipboardexpand all lines: docs/dynamic-plugins/dynamic-plugins.md
+75-7
Original file line number
Diff line number
Diff line change
@@ -542,7 +542,7 @@ global:
542
542
543
543
Compared to the backend plugins, where mount points are defined in code and consumed by the backend plugin manager, frontend plugins require additional configuration in the `app-config.yaml`. A plugin missing this configuration will not be loaded into the application and will not be displayed.
544
544
545
-
Similarly to traditional Backstage instances, there are 3 types of functionality a dynamic frontend plugin can offer:
545
+
Similarly to traditional Backstage instances, there are various kinds of functionality a dynamic frontend plugin can offer:
546
546
547
547
- Full new page that declares a completely new route in the app
548
548
- Extension to existing page via router `bind`ings
@@ -631,8 +631,37 @@ Each plugin can expose multiple routes and each route is required to define its
631
631
- `path` - Unique path in the app. Cannot override existing routes with the exception of the `/` home route: the main home page can be replaced via the dynamic plugins mechanism.
632
632
- `module`- Optional. Since dynamic plugins can expose multiple distinct modules, you may need to specify which set of assets you want to access within the plugin. If not provided, the default module named `PluginRoot` is used. This is the same as the key in `scalprum.exposedModules` key in plugin's `package.json`.
633
633
- `importName`- Optional. The actual component name that should be rendered as a standalone page. If not specified the `default` export is used.
634
-
- `menuItem`- This property allows users to extend the main sidebar navigation and point to their new route. It accepts `text` and `icon` properties. `icon` refers to a Backstage system icon name. See [Backstage system icons](https://backstage.io/docs/getting-started/app-custom-theme/#icons) for the list of default icons and [Extending Icons Library](#extend-internal-library-of-available-icons) to extend this with dynamic plugins.
635
-
- `config.props`- Optional. Additionally you can pass React props to the component.
634
+
- `menuItem` - This property allows users to extend the main sidebar navigation and point to their new route. It accepts the following properties:
635
+
- `text`: The label shown to the user
636
+
- `icon`: refers to a Backstage system icon name. See [Backstage system icons](https://backstage.io/docs/getting-started/app-custom-theme/#icons) for the list of default icons and [Extending Icons Library](#extend-internal-library-of-available-icons) to extend this with dynamic plugins.
637
+
- `importName`: optional name of an exported SidebarItem component. The component will receive a `to` property as well as any properties specified in `config.props`
638
+
- `config`- An optional field which is a holder to pass `props` to a custom sidebar item
639
+
640
+
A custom SidebarItem offers opportunities to provide a richer user experience such as notification badges. The component should accept the following properties:
641
+
642
+
```typescript
643
+
export type MySidebarItemProps = {
644
+
to: string; // supplied by the sidebar during rendering, this will be the path configured for the dynamicRoute
645
+
};
646
+
```
647
+
648
+
Other properties can be specified as well and configured using the `config.props` property on the dynamic route.
649
+
650
+
Here is an example configuration specifying a custom SidebarItem component:
651
+
652
+
```yaml
653
+
dynamicPlugins:
654
+
frontend:
655
+
my-dynamic-plugin-package-name:
656
+
dynamicRoutes:
657
+
- importName: CustomPage
658
+
menuItem:
659
+
config:
660
+
props:
661
+
text: Click Me!
662
+
importName: SimpleSidebarItem
663
+
path: /custom_page
664
+
```
636
665
637
666
#### Menu items
638
667
@@ -749,6 +778,7 @@ The following mount points are available:
Note: Mount points within Catalog aka `entity.page.*` are rendered as tabs. They become visible only if at least one plugin contributes to them or they can render static content (see column 3 in previous table).
801
+
Mount points within Catalog aka `entity.page.*` are rendered as tabs. They become visible only if at least one plugin contributes to them or they can render static content (see column 3 in previous table).
772
802
773
803
Each `entity.page.*` mount point has 2 complementary variations:
774
804
775
805
- `*/context`type that serves to create React contexts
776
806
- `*/cards`type for regular React components
777
807
808
+
Here is an example of the overall configuration structure of a mount point:
809
+
778
810
```yaml
779
811
# app-config.yaml
780
812
dynamicPlugins:
@@ -814,6 +846,33 @@ Each mount point supports additional configuration:
814
846
- `hasAnnotation`: Accepts a string or a list of string with annotation keys. For example `hasAnnotation: my-annotation` will render the component only for entities that have `metadata.annotations['my-annotation']` defined.
815
847
- condition imported from the plugin's `module`: Must be function name exported from the same `module` within the plugin. For example `isMyPluginAvailable` will render the component only if `isMyPluginAvailable` function returns `true`. The function must have following signature: `(e: Entity) => boolean`
816
848
849
+
The entity page also supports adding more items to the context menu at the top right of the page. Components targeting the `entity.context.menu` mount point have some constraints to follow. The exported component should be some form of dialog wrapper component that accepts an `open` boolean property and an `onClose` event handler property, like so:
850
+
851
+
```typescript
852
+
export type SimpleDialogProps = {
853
+
open: boolean;
854
+
onClose: () => void;
855
+
};
856
+
```
857
+
858
+
The context menu entry can be configured via the `props` configuration entry for the mount point. The `title` and `icon` properties will set the menu item's text and icon. Any system icon or icon added via a dynamic plugin can be used. Here is an example configuration:
859
+
860
+
```yaml
861
+
dynamicPlugins:
862
+
frontend:
863
+
my-dynamic-plugin-package:
864
+
appIcons:
865
+
- name: dialogIcon
866
+
importName: DialogIcon
867
+
mountPoints:
868
+
- mountPoint: entity.context.menu
869
+
importName: SimpleDialog
870
+
config:
871
+
props:
872
+
title: Open Simple Dialog
873
+
icon: dialogIcon
874
+
```
875
+
817
876
#### Customizing and Adding Entity tabs
818
877
819
878
Out of the box the frontend system provides an opinionated set of tabs for catalog entity views. This set of tabs can be further customized and extended as needed via the `entityTabs` configuration:
@@ -872,7 +931,18 @@ Backstage offers an Utility API mechanism that provide ways for plugins to commu
872
931
- Custom plugin-made API that can be already self contained within any plugin (including dynamic plugins)
873
932
- [App API implementations and overrides](https://backstage.io/docs/api/utility-apis/#app-apis) which needs to be added separately.
874
933
875
-
Dynamic plugins provides you with a way to utilize the App API concept via `apiFactories` configuration:
934
+
and a plugin can potentially expose multiple API Factories. Dynamic plugins allow a couple different ways to take advantage of this functionality.
935
+
936
+
If a dynamic plugin exports the plugin object returned by `createPlugin`, it will be supplied to the `createApp` API and all API factories exported by the plugin will be automatically registered and available in the frontend application. Dynamic plugins that follow this pattern should not use the `apiFactories` configuration. Also, if a dynamic plugin only contains API factories and follows this pattern, it will just be necessary to add an entry to the `dynamicPlugins.frontend` config for the dynamic plugin package name, for example:
937
+
938
+
```yaml
939
+
# app-config.yaml
940
+
dynamicPlugins:
941
+
frontend:
942
+
my-dynamic-plugin-package-with-api-factories: {}
943
+
```
944
+
945
+
However if the dynamic plugin doesn't export it's plugin object then it will be necessary to explicitly configure each API factory that should be registered with the `createApp` API via the `apiFactories` configuration:
876
946
877
947
```yaml
878
948
# app-config.yaml
@@ -884,8 +954,6 @@ dynamicPlugins:
884
954
module: CustomModule # Optional, same as key in `scalprum.exposedModules` key in plugin's `package.json`
885
955
```
886
956
887
-
Each plugin can expose multiple API Factories and each factory is required to define its `importName` (if it differs from the default export).
888
-
889
957
- `importName` is an optional import name that reference a `AnyApiFactory<{}>` implementation. Defaults to `default` export.
890
958
- `module`is an optional argument which allows you to specify which set of assets you want to access within the plugin. If not provided, the default module named `PluginRoot` is used. This is the same as the key in `scalprum.exposedModules` key in plugin's `package.json`.
0 commit comments