diff --git a/microsite/sidebars.json b/microsite/sidebars.json index bfe1b9c6e9..29fb3a0534 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -212,7 +212,6 @@ "plugins/structure-of-a-plugin", "plugins/integrating-plugin-into-software-catalog", "plugins/integrating-search-into-plugins", - "plugins/customization", "plugins/composability", "plugins/analytics", { diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 7a5d7f2138..148020b409 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -24,7 +24,7 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/packages/core-plugin-api/src/extensions/extensions.tsx b/packages/core-plugin-api/src/extensions/extensions.tsx index c0d54af2c1..149ea1f520 100644 --- a/packages/core-plugin-api/src/extensions/extensions.tsx +++ b/packages/core-plugin-api/src/extensions/extensions.tsx @@ -21,7 +21,7 @@ import { RouteRef, useRouteRef } from '../routing'; import { attachComponentData } from './componentData'; import { Extension, BackstagePlugin } from '../plugin'; import { PluginErrorBoundary } from './PluginErrorBoundary'; -import { PluginOptionsProvider } from '../plugin-options'; +import { PluginProvider } from '../plugin-options'; /** * Lazy or synchronous retrieving of extension components. @@ -246,11 +246,9 @@ export function createReactExtension< ...(mountPoint && { routeRef: mountPoint.id }), }} > - + - + diff --git a/packages/core-plugin-api/src/plugin-options/index.ts b/packages/core-plugin-api/src/plugin-options/index.ts index 83901f526a..937cf49032 100644 --- a/packages/core-plugin-api/src/plugin-options/index.ts +++ b/packages/core-plugin-api/src/plugin-options/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { usePluginOptions, PluginOptionsProvider } from './usePluginOptions'; +export { usePluginOptions, PluginProvider } from './usePluginOptions'; diff --git a/packages/core-plugin-api/src/plugin-options/usePluginOptions.test.tsx b/packages/core-plugin-api/src/plugin-options/usePluginOptions.test.tsx index ea4c1d383e..268e191cec 100644 --- a/packages/core-plugin-api/src/plugin-options/usePluginOptions.test.tsx +++ b/packages/core-plugin-api/src/plugin-options/usePluginOptions.test.tsx @@ -16,21 +16,27 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; -import { usePluginOptions, PluginOptionsProvider } from './usePluginOptions'; +import { usePluginOptions, PluginProvider } from './usePluginOptions'; +import { createPlugin, PluginOptions } from '../plugin'; describe('usePluginOptions', () => { it('should provide a versioned value to hook', () => { + const plugin = createPlugin({ + id: 'my-plugin', + options: { 'key-1': 'value-1', 'key-2': 'value-2' }, + }); + const rendered = renderHook(() => usePluginOptions(), { wrapper: ({ children }) => ( - - {children} - + {children} ), }); - expect(rendered.result.current).toEqual({ + const config = rendered.result.current.config as unknown as { + options: PluginOptions; + }; + + expect(config.options).toEqual({ 'key-1': 'value-1', 'key-2': 'value-2', }); diff --git a/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx b/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx index 1e667e09ea..fc136e960d 100644 --- a/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx +++ b/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx @@ -19,7 +19,7 @@ import { createVersionedValueMap, useVersionedContext, } from '@backstage/version-bridge'; -import { PluginOptions } from '../plugin'; +import { BackstagePlugin, PluginOptions } from '../plugin'; import React, { ReactNode } from 'react'; const contextKey: string = 'plugin-options-context'; @@ -31,14 +31,17 @@ const contextKey: string = 'plugin-options-context'; */ export interface PluginOptionsProviderProps { children: ReactNode; - pluginOptions?: PluginOptions; + plugin?: BackstagePlugin; } -export const PluginOptionsProvider = ({ +export const PluginProvider = ({ children, - pluginOptions, + plugin, }: PluginOptionsProviderProps): JSX.Element => { - const value = { pluginOptions }; + const providerPlugin = plugin as unknown as { + getPluginOptions(): PluginOptions; + }; + const value = { pluginOptions: providerPlugin.getPluginOptions() }; const { Provider } = createVersionedContext<{ 1: PluginOptions }>(contextKey); return ( @@ -51,7 +54,7 @@ export const PluginOptionsProvider = ({ * Grab the current entity from the context, throws if the entity has not yet been loaded * or is not available. * - * @public + * @alpha */ export function usePluginOptions< TPluginOptions extends PluginOptions = PluginOptions, diff --git a/packages/core-plugin-api/src/plugin/Plugin.tsx b/packages/core-plugin-api/src/plugin/Plugin.tsx index fb2f304b46..a99885cfe8 100644 --- a/packages/core-plugin-api/src/plugin/Plugin.tsx +++ b/packages/core-plugin-api/src/plugin/Plugin.tsx @@ -60,15 +60,15 @@ export class PluginImpl< return extension.expose(this); } - reconfigure(options: PluginInputOptions): void { - if (this.config.configure) { - this.config.options = this.config.configure(options); + __experimentalReconfigure(options: PluginInputOptions): void { + if (this.config.__experimentalConfigure) { + this.config.options = this.config.__experimentalConfigure(options); } } getPluginOptions(): PluginOptions { - if (this.config.configure && !this.config.options) { - this.config.options = this.config.configure(); + if (this.config.__experimentalConfigure && !this.config.options) { + this.config.options = this.config.__experimentalConfigure(); } return this.config.options ?? ({} as PluginOptions); } diff --git a/packages/core-plugin-api/src/plugin/types.ts b/packages/core-plugin-api/src/plugin/types.ts index fa8778ce93..4dbb9e0e41 100644 --- a/packages/core-plugin-api/src/plugin/types.ts +++ b/packages/core-plugin-api/src/plugin/types.ts @@ -68,10 +68,9 @@ export type BackstagePlugin< */ getFeatureFlags(): Iterable; provide(extension: Extension): T; - getPluginOptions(): PluginOptions; - reconfigure(options: PluginInputOptions): void; routes: Routes; externalRoutes: ExternalRoutes; + __experimentalReconfigure(options: PluginInputOptions): void; }; /** @@ -99,7 +98,7 @@ export type PluginConfig< externalRoutes?: ExternalRoutes; featureFlags?: PluginFeatureFlagConfig[]; options?: PluginOptions; - configure?(options?: PluginInputOptions): PluginOptions; + __experimentalConfigure?(options?: PluginInputOptions): PluginOptions; }; /** diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 4ffc82c2b0..1e1c2c14b5 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -34,7 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-catalog": "^1.3.1-next.0", + "@backstage/plugin-catalog": "1.4.0-next.2", "@backstage/plugin-catalog-react": "^1.1.2-next.0" }, "peerDependencies": { diff --git a/plugins/catalog-customized/src/plugin.ts b/plugins/catalog-customized/src/plugin.ts index e46eb17192..e3830ee31c 100644 --- a/plugins/catalog-customized/src/plugin.ts +++ b/plugins/catalog-customized/src/plugin.ts @@ -16,18 +16,8 @@ import { catalogPlugin } from '@backstage/plugin-catalog'; -import { - EntityOwnerPicker, - EntityTypePicker, - UserListPicker, -} from './components'; - -catalogPlugin.reconfigure({ - EntityOwnerPicker, - EntityTypePicker, - UserListPicker, +catalogPlugin.__experimentalReconfigure({ createButtonTitle: 'Maybe Create', - showButtonText: 'Mine catalog entities', }); export const customizedCatalog = catalogPlugin; diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index da31fa6726..f06bbc8acd 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -34,14 +34,17 @@ import { EntityLifecyclePicker, EntityListProvider, EntityProcessingStatusPicker, + EntityOwnerPicker, EntityTagPicker, + EntityTypePicker, UserListFilterKind, + UserListPicker, } from '@backstage/plugin-catalog-react'; import React from 'react'; import { createComponentRouteRef } from '../../routes'; import { CatalogTable, CatalogTableRow } from '../CatalogTable'; import { CatalogKindHeader } from '../CatalogKindHeader'; -import { CatalogPageOptionsProps } from '../../types'; +import { CatalogPluginOptions } from '../../options'; /** * Props for root catalog pages. @@ -68,13 +71,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; const createComponentLink = useRouteRef(createComponentRouteRef); - const { - EntityOwnerPicker, - EntityTypePicker, - UserListPicker, - createButtonTitle, - showButtonText, - } = usePluginOptions(); + const { createButtonTitle } = usePluginOptions(); return ( @@ -87,7 +84,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { title={createButtonTitle} to={createComponentLink && createComponentLink()} /> - ${showButtonText} + All your software catalog entities diff --git a/plugins/catalog/src/types.ts b/plugins/catalog/src/options.ts similarity index 64% rename from plugins/catalog/src/types.ts rename to plugins/catalog/src/options.ts index 29997d1368..5b0e0767e3 100644 --- a/plugins/catalog/src/types.ts +++ b/plugins/catalog/src/options.ts @@ -14,15 +14,6 @@ * limitations under the License. */ -import { - EntityTypePickerProps, - UserListPickerProps, -} from '@backstage/plugin-catalog-react'; - -export type CatalogPageOptionsProps = { - EntityOwnerPicker: () => JSX.Element | null; - EntityTypePicker: (props: EntityTypePickerProps) => JSX.Element | null; - UserListPicker: (props: UserListPickerProps) => JSX.Element | null; +export type CatalogPluginOptions = { createButtonTitle: string; - showButtonText: string; }; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index ce68fafcbc..1fd52a82a8 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -18,10 +18,7 @@ import { CatalogClient } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { catalogApiRef, - EntityOwnerPicker, entityRouteRef, - EntityTypePicker, - UserListPicker, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { createComponentRouteRef, viewTechDocRouteRef } from './routes'; @@ -34,6 +31,7 @@ import { fetchApiRef, storageApiRef, PluginOptions, + PluginInputOptions, } from '@backstage/core-plugin-api'; import { DefaultStarredEntitiesApi } from './apis'; import { AboutCardProps } from './components/AboutCard'; @@ -48,8 +46,6 @@ import { HasSystemsCardProps } from './components/HasSystemsCard'; import { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard'; import { rootRouteRef } from './routes'; -export interface PluginInputOptions {} - /** @public */ export const catalogPlugin = createPlugin({ id: 'catalog', @@ -78,13 +74,9 @@ export const catalogPlugin = createPlugin({ createComponent: createComponentRouteRef, viewTechDoc: viewTechDocRouteRef, }, - configure(options?: PluginInputOptions): PluginOptions { + __experimentalConfigure(options?: PluginInputOptions): PluginOptions { const defaultOptions = { - EntityOwnerPicker, - EntityTypePicker, - UserListPicker, createButtonTitle: 'Create', - showButtonText: 'All your software catalog entities', }; if (!options) { return defaultOptions; diff --git a/yarn.lock b/yarn.lock index 4393aedfb8..68e9a56a40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1602,6 +1602,51 @@ zen-observable "^0.8.15" zod "^3.11.6" +"@backstage/core-components@^0.9.6-next.1": + version "0.9.6-next.1" + resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.6-next.1.tgz#52fc93339ee9f9adf11833fb6f54a6a2c7f6526e" + integrity sha512-TTNGzypjcDI7xAqSz+d3SLN7W2duHiOAebCiyoi38MHzHeQGjga7feBu0HuxEcXxfn8i6E0j3cdmZIlCIlcUXA== + dependencies: + "@backstage/config" "^1.0.1" + "@backstage/core-plugin-api" "^1.0.3" + "@backstage/errors" "^1.1.0-next.0" + "@backstage/theme" "^0.2.16-next.0" + "@backstage/version-bridge" "^1.0.1" + "@material-table/core" "^3.1.0" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + "@react-hookz/web" "^14.0.0" + "@types/react-sparklines" "^1.7.0" + "@types/react-text-truncate" "^0.14.0" + ansi-regex "^6.0.1" + classnames "^2.2.6" + d3-selection "^3.0.0" + d3-shape "^3.0.0" + d3-zoom "^3.0.0" + dagre "^0.8.5" + history "^5.0.0" + immer "^9.0.1" + lodash "^4.17.21" + pluralize "^8.0.0" + prop-types "^15.7.2" + qs "^6.9.4" + rc-progress "3.3.3" + react-helmet "6.1.0" + react-hook-form "^7.12.2" + react-markdown "^8.0.0" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-sparklines "^1.7.0" + react-syntax-highlighter "^15.4.5" + react-text-truncate "^0.19.0" + react-use "^17.3.2" + react-virtualized-auto-sizer "^1.0.6" + react-window "^1.8.6" + remark-gfm "^3.0.1" + zen-observable "^0.8.15" + zod "^3.11.6" + "@backstage/errors@^1.0.0": version "1.0.0" resolved "https://registry.npmjs.org/@backstage/errors/-/errors-1.0.0.tgz#08ebf53afdeaca32362955ea8551e8ffa0bb3cd7" @@ -1677,6 +1722,33 @@ yaml "^1.10.0" zen-observable "^0.8.15" +"@backstage/plugin-catalog@^1.3.1-next.0": + version "1.3.1-next.1" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog/-/plugin-catalog-1.3.1-next.1.tgz#c191a6bc8bbef485a40dffe0a1d0ab9114497be2" + integrity sha512-aPSpX33ZHdok0ruJg5k7BPQd28k4ARjPHwEQCNvAVXLRJHIeU63ZOgsQPQ/iWSutRJE/6seELnZ1a4tWSGYe6Q== + dependencies: + "@backstage/catalog-client" "^1.0.4-next.1" + "@backstage/catalog-model" "^1.1.0-next.1" + "@backstage/core-components" "^0.9.6-next.1" + "@backstage/core-plugin-api" "^1.0.3" + "@backstage/errors" "^1.1.0-next.0" + "@backstage/integration-react" "^1.1.2-next.1" + "@backstage/plugin-catalog-common" "^1.0.4-next.0" + "@backstage/plugin-catalog-react" "^1.1.2-next.1" + "@backstage/plugin-search-common" "^0.3.6-next.0" + "@backstage/plugin-search-react" "^0.2.2-next.1" + "@backstage/theme" "^0.2.16-next.0" + "@backstage/types" "^1.0.0" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + history "^5.0.0" + lodash "^4.17.21" + react-helmet "6.1.0" + react-router "6.0.0-beta.0" + react-use "^17.2.4" + zen-observable "^0.8.15" + "@backstage/plugin-home@^0.4.19", "@backstage/plugin-home@^0.4.22": version "0.4.22" resolved "https://registry.npmjs.org/@backstage/plugin-home/-/plugin-home-0.4.22.tgz#efc54ebffb83a2a36dcd43e65142c30be5d8559d" @@ -12690,6 +12762,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: "@backstage/plugin-todo" "^0.2.9-next.2" "@backstage/plugin-user-settings" "^0.4.6-next.2" "@backstage/theme" "^0.2.16-next.1" + "@internal/plugin-catalog-customized" "1.2.1-next.1" "@material-ui/core" "^4.12.2" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.57"