Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(fab): add new mountpoints support for providers and listeners #2199

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rhdh/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/roadiehq-backstage-plugin-
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace-backend-dynamic/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace-backend-dynamic/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-dynamic-home-page/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-dynamic-home-page/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-marketplace-dynamic/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-marketplace-dynamic/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-bulk-import/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-bulk-import/package.json
Expand Down
11 changes: 11 additions & 0 deletions app-config.dynamic-plugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ dynamicPlugins:
config:
layout:
position: above-main-content
red-hat-developer-hub.backstage-plugin-global-floating-action-button:
mountPoints:
- mountPoint: application/listener
importName: DynamicGlobalFloatingActionButton
- mountPoint: global.floatingactionbutton/component
importName: NullComponent
config:
icon: github
label: Git
toolTip: Github
to: https://github.com/redhat-developer/rhdh
red-hat-developer-hub.backstage-plugin-dynamic-home-page:
dynamicRoutes:
- path: /
Expand Down
1 change: 1 addition & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace-backend-dynamic/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-marketplace-backend-dynamic/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-dynamic-home-page/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-dynamic-home-page/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-marketplace-dynamic/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-marketplace-dynamic/package.json
COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-bulk-import/package.json ./dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-bulk-import/package.json
Expand Down Expand Up @@ -229,7 +230,7 @@
COPY --from=build $CONTAINER_SOURCE/dynamic-plugins/dist/ ./dynamic-plugins/dist/

# RHIDP-4220 - make Konflux preflight and EC checks happy - [check-container] Create a directory named /licenses and include all relevant licensing
COPY $EXTERNAL_SOURCE/LICENSE /licenses/

Check warning on line 233 in docker/Dockerfile

View workflow job for this annotation

GitHub Actions / Build Image

Variables should be defined before their use

UndefinedVar: Usage of undefined variable '$EXTERNAL_SOURCE' More info: https://docs.docker.com/go/dockerfile/rule/undefined-var/

# Copy script to gather dynamic plugins; copy embedded dynamic plugins to root folder; fix permissions
COPY docker/install-dynamic-plugins.py docker/install-dynamic-plugins.sh ./
Expand Down Expand Up @@ -257,7 +258,7 @@

# gGVM6sYRK0D0ndVX22BOtS7NRcxPej8t is key for dev environment
# Upstream only - Use dev key in all branches
ENV SEGMENT_WRITE_KEY=gGVM6sYRK0D0ndVX22BOtS7NRcxPej8t

Check warning on line 261 in docker/Dockerfile

View workflow job for this annotation

GitHub Actions / Build Image

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "SEGMENT_WRITE_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV SEGMENT_TEST_MODE=false

# RHIDP-2217: corporate proxy support (configured using 'global-agent' for 'node-fetch' calls and 'undici' for 'fetch' calls)
Expand Down
36 changes: 36 additions & 0 deletions docs/dynamic-plugins/frontend-plugin-wiring.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,42 @@ Each global header entry requires the following attributes:

Users can configure multiple global headers at different positions by adding entries to the `mountPoints` field.

### Adding application listeners

The users can add application listeners using the `application/listener` mount point. Below is an example that uses the aforesaid mount point:

```yaml
# app-config.yaml
dynamicPlugins:
frontend:
<package_name>: # plugin_package_name same as `scalprum.name` key in plugin's `package.json`
mountPoints:
- mountPoint: application/listener
importName: <exported listener component>
```

Users can configure multiple application listeners by adding entries to the `mountPoints` field.

### Adding application providers

The users can add application providers using the `application/provider` mount point. Below is an example that uses the aforesaid mount point to configure a context provider:

```yaml
# app-config.yaml
dynamicPlugins:
frontend:
<package_name>: # plugin_package_name same as `scalprum.name` key in plugin's `package.json`
dynamicRoutes:
- path: /<route>
importName: Component # Component you want to load on the route
mountPoints:
- mountPoint: application/provider
importName: <exported provider component>
```

Users can configure multiple application providers by adding entries to the `mountPoints` field.


## Customizing and Adding Entity tabs

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:
Expand Down
18 changes: 18 additions & 0 deletions dynamic-plugins.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,24 @@ plugins:
layout:
position: above-main-content

# Group: Global floating action button
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-floating-action-button
disabled: true
pluginConfig:
dynamicPlugins:
frontend:
red-hat-developer-hub.backstage-plugin-global-floating-action-button:
mountPoints:
- mountPoint: application/listener
importName: DynamicGlobalFloatingActionButton
- mountPoint: global.floatingactionbutton/component
importName: NullComponent
config:
icon: github
label: 'Git'
toolTip: 'Github'
to: https://github.com/redhat-developer/rhdh

# Homepage
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-dynamic-home-page
disabled: false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist-dynamic
dist-scalprum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("@backstage/cli/config/eslint-factory")(__dirname);
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "red-hat-developer-hub-backstage-plugin-global-floating-action-button",
"version": "0.0.6",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"backstage": {
"role": "frontend-plugin",
"supported-versions": "1.35.0",
"pluginId": "red-hat-developer-hub-backstage-plugin-global-floating-action-button",
"pluginPackages": [
"red-hat-developer-hub-backstage-plugin-global-floating-action-button"
]
},
"sideEffects": false,
"scripts": {
"tsc": "tsc",
"build": "backstage-cli package build",
"lint:check": "backstage-cli package lint",
"test": "backstage-cli package test --passWithNoTests --coverage",
"clean": "backstage-cli package clean",
"export-dynamic": "janus-cli package export-dynamic-plugin --in-place",
"export-dynamic:clean": "run export-dynamic --clean"
},
"dependencies": {
"@mui/material": "5.16.14",
"@red-hat-developer-hub/backstage-plugin-global-floating-action-button": "0.0.6"
},
"devDependencies": {
"@backstage/cli": "0.29.5",
"@janus-idp/cli": "3.0.0",
"typescript": "5.7.3"
},
"scalprum": {
"name": "red-hat-developer-hub.backstage-plugin-global-floating-action-button",
"exposedModules": {
"PluginRoot": "./src/index.ts"
}
},
"files": [
"dist",
"dist-scalprum"
],
"keywords": [
"backstage",
"plugin"
],
"repository": {
"type": "git",
"url": "https://github.com/redhat-developer/rhdh",
"directory": "dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button"
},
"author": "Red Hat",
"homepage": "https://red.ht/rhdh",
"bugs": "https://issues.redhat.com/browse/RHIDP"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { unstable_ClassNameGenerator as ClassNameGenerator } from "@mui/material/className";

ClassNameGenerator.configure((componentName) => {
return componentName.startsWith("v5-")
? componentName
: `v5-${componentName}`;
});

export * from "@red-hat-developer-hub/backstage-plugin-global-floating-action-button";
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@backstage/cli/config/tsconfig.json",
"include": ["src", "dev", "migrations"],
"exclude": ["node_modules"],
"compilerOptions": {
"outDir": "../../../dist-types/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button",
"rootDir": "."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": ["//"],
"tasks": {
"tsc": {
"outputs": [
"../../../dist-types/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/**"
]
}
}
}
123 changes: 64 additions & 59 deletions packages/app/src/components/AppBase/AppBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { entityPage } from '../catalog/EntityPage';
import DynamicRootContext from '../DynamicRoot/DynamicRootContext';
import { LearningPaths } from '../learningPaths/LearningPathsPage';
import { Root } from '../Root';
import { ApplicationListener } from '../Root/ApplicationListener';
import { ApplicationProvider } from '../Root/ApplicationProvider';
import ConfigUpdater from '../Root/ConfigUpdater';
import { SearchPage } from '../search/SearchPage';
import { settingsPage } from '../UserSettings/SettingsPages';
Expand Down Expand Up @@ -74,66 +76,69 @@ const AppBase = () => {
<OAuthRequestDialog />
<AppRouter>
<ConfigUpdater />
<ApplicationListener />
<Root>
<FlatRoutes>
<Route
path="/catalog"
element={
<CatalogIndexPage pagination columns={myCustomColumnsFunc} />
}
/>
<Route
path="/catalog/:namespace/:kind/:name"
element={<CatalogEntityPage />}
>
{entityPage(entityTabOverrides)}
</Route>
<Route
path="/create"
element={
<ScaffolderPage
headerOptions={{ title: 'Software Templates' }}
/>
}
>
<ScaffolderFieldExtensions>
{scaffolderFieldExtensions.map(
({ scope, module, importName, Component }) => (
<Component key={`${scope}-${module}-${importName}`} />
),
)}
</ScaffolderFieldExtensions>
scaffolderFieldExtensions
</Route>
<Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/catalog-import"
element={
<RequirePermission permission={catalogEntityCreatePermission}>
<CatalogImportPage />
</RequirePermission>
}
/>
<Route path="/search" element={<BackstageSearchPage />}>
<SearchPage />
</Route>
<Route path="/settings" element={<UserSettingsPage />}>
{settingsPage}
</Route>
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
<Route path="/learning-paths" element={<LearningPaths />} />
{dynamicRoutes.map(
({ Component, staticJSXContent, path, config: { props } }) => (
<Route
key={path}
path={path}
element={<Component {...props} />}
>
{staticJSXContent}
</Route>
),
)}
</FlatRoutes>
<ApplicationProvider>
<FlatRoutes>
<Route
path="/catalog"
element={
<CatalogIndexPage pagination columns={myCustomColumnsFunc} />
}
/>
<Route
path="/catalog/:namespace/:kind/:name"
element={<CatalogEntityPage />}
>
{entityPage(entityTabOverrides)}
</Route>
<Route
path="/create"
element={
<ScaffolderPage
headerOptions={{ title: 'Software Templates' }}
/>
}
>
<ScaffolderFieldExtensions>
{scaffolderFieldExtensions.map(
({ scope, module, importName, Component }) => (
<Component key={`${scope}-${module}-${importName}`} />
),
)}
</ScaffolderFieldExtensions>
scaffolderFieldExtensions
</Route>
<Route path="/api-docs" element={<ApiExplorerPage />} />
<Route
path="/catalog-import"
element={
<RequirePermission permission={catalogEntityCreatePermission}>
<CatalogImportPage />
</RequirePermission>
}
/>
<Route path="/search" element={<BackstageSearchPage />}>
<SearchPage />
</Route>
<Route path="/settings" element={<UserSettingsPage />}>
{settingsPage}
</Route>
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
<Route path="/learning-paths" element={<LearningPaths />} />
{dynamicRoutes.map(
({ Component, staticJSXContent, path, config: { props } }) => (
<Route
key={path}
path={path}
element={<Component {...props} />}
>
{staticJSXContent}
</Route>
),
)}
</FlatRoutes>
</ApplicationProvider>
</Root>
</AppRouter>
</AppProvider>
Expand Down
20 changes: 20 additions & 0 deletions packages/app/src/components/Root/ApplicationListener.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useContext } from 'react';

import { ErrorBoundary } from '@backstage/core-components';

import DynamicRootContext from '../DynamicRoot/DynamicRootContext';

export const ApplicationListener = () => {
const { mountPoints } = useContext(DynamicRootContext);
const listeners = mountPoints['application/listener'] ?? [];
return listeners.map(({ Component }, index) => {
return (
<ErrorBoundary
// eslint-disable-next-line react/no-array-index-key
key={index}
>
<Component />
</ErrorBoundary>
);
});
};
28 changes: 28 additions & 0 deletions packages/app/src/components/Root/ApplicationProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useContext, useMemo } from 'react';

import { ErrorBoundary } from '@backstage/core-components';

import DynamicRootContext from '../DynamicRoot/DynamicRootContext';

export const ApplicationProvider = ({
children,
}: React.PropsWithChildren<{}>) => {
const { mountPoints } = useContext(DynamicRootContext);
const providers = useMemo(
() => mountPoints['application/provider'] ?? [],
[mountPoints],
);
if (providers.length === 0) {
return children;
}
return providers.reduceRight((acc, { Component }, index) => {
return (
<ErrorBoundary
// eslint-disable-next-line react/no-array-index-key
key={index}
>
<Component>{acc}</Component>
</ErrorBoundary>
);
}, children);
};
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export const InternalPluginsMap: Record<string, string> = {
'./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-bulk-import',
'red-hat-developer-hub-backstage-plugin-global-header':
'./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-header',
'red-hat-developer-hub-backstage-plugin-global-floating-action-button':
'./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-floating-action-button',
'red-hat-developer-hub-backstage-plugin-dynamic-home-page':
'./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-dynamic-home-page',
'red-hat-developer-hub-backstage-plugin-marketplace':
Expand Down
Loading
Loading