From f22d52210f0e2c41cfcf75444d27ea4c4f76851f Mon Sep 17 00:00:00 2001 From: debsmita1 Date: Fri, 17 Jan 2025 00:31:31 +0530 Subject: [PATCH] feat(fab): add new mountpoints support for providers and listeners Signed-off-by: debsmita1 Signed-off-by: Christoph Jerolimov --- .rhdh/docker/Dockerfile | 1 + app-config.dynamic-plugins.yaml | 11 ++ docker/Dockerfile | 1 + .../dynamic-plugins/frontend-plugin-wiring.md | 36 +++++ dynamic-plugins.default.yaml | 18 +++ .../.eslintignore | 2 + .../.eslintrc.js | 1 + .../package.json | 61 +++++++++ .../src/index.ts | 9 ++ .../tsconfig.json | 9 ++ .../turbo.json | 10 ++ .../app/src/components/AppBase/AppBase.tsx | 123 +++++++++--------- .../components/Root/ApplicationListener.tsx | 20 +++ .../components/Root/ApplicationProvider.tsx | 28 ++++ .../src/components/InternalPluginsMap.ts | 2 + yarn.lock | 34 ++++- 16 files changed, 306 insertions(+), 60 deletions(-) create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintignore create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintrc.js create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/src/index.ts create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/tsconfig.json create mode 100644 dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/turbo.json create mode 100644 packages/app/src/components/Root/ApplicationListener.tsx create mode 100644 packages/app/src/components/Root/ApplicationProvider.tsx diff --git a/.rhdh/docker/Dockerfile b/.rhdh/docker/Dockerfile index e69da0be5c..c3e2cf824d 100644 --- a/.rhdh/docker/Dockerfile +++ b/.rhdh/docker/Dockerfile @@ -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 diff --git a/app-config.dynamic-plugins.yaml b/app-config.dynamic-plugins.yaml index 555ac814fb..a5bf7354ca 100644 --- a/app-config.dynamic-plugins.yaml +++ b/app-config.dynamic-plugins.yaml @@ -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: / diff --git a/docker/Dockerfile b/docker/Dockerfile index f11467e122..117ed0a413 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -75,6 +75,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 diff --git a/docs/dynamic-plugins/frontend-plugin-wiring.md b/docs/dynamic-plugins/frontend-plugin-wiring.md index 90e587a97d..e0ac379f28 100644 --- a/docs/dynamic-plugins/frontend-plugin-wiring.md +++ b/docs/dynamic-plugins/frontend-plugin-wiring.md @@ -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: + : # plugin_package_name same as `scalprum.name` key in plugin's `package.json` + mountPoints: + - mountPoint: application/listener + importName: +``` + +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: + : # plugin_package_name same as `scalprum.name` key in plugin's `package.json` + dynamicRoutes: + - path: / + importName: Component # Component you want to load on the route + mountPoints: + - mountPoint: application/provider + importName: +``` + +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: diff --git a/dynamic-plugins.default.yaml b/dynamic-plugins.default.yaml index 5387d5676e..2233c9d3f3 100644 --- a/dynamic-plugins.default.yaml +++ b/dynamic-plugins.default.yaml @@ -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 diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintignore b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintignore new file mode 100644 index 0000000000..55289f4a23 --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintignore @@ -0,0 +1,2 @@ +dist-dynamic +dist-scalprum diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintrc.js b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintrc.js new file mode 100644 index 0000000000..958d722cb2 --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require("@backstage/cli/config/eslint-factory")(__dirname); diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json new file mode 100644 index 0000000000..dfc48b4e19 --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/package.json @@ -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.6", + "@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" +} diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/src/index.ts b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/src/index.ts new file mode 100644 index 0000000000..666086b6a3 --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/src/index.ts @@ -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"; diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/tsconfig.json b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/tsconfig.json new file mode 100644 index 0000000000..040da5f1bb --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/tsconfig.json @@ -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": "." + } +} diff --git a/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/turbo.json b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/turbo.json new file mode 100644 index 0000000000..4fd8ddbc9c --- /dev/null +++ b/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/turbo.json @@ -0,0 +1,10 @@ +{ + "extends": ["//"], + "tasks": { + "tsc": { + "outputs": [ + "../../../dist-types/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button/**" + ] + } + } +} diff --git a/packages/app/src/components/AppBase/AppBase.tsx b/packages/app/src/components/AppBase/AppBase.tsx index 62ea3365b0..3e0c525793 100644 --- a/packages/app/src/components/AppBase/AppBase.tsx +++ b/packages/app/src/components/AppBase/AppBase.tsx @@ -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'; @@ -74,66 +76,69 @@ const AppBase = () => { + - - - } - /> - } - > - {entityPage(entityTabOverrides)} - - - } - > - - {scaffolderFieldExtensions.map( - ({ scope, module, importName, Component }) => ( - - ), - )} - - scaffolderFieldExtensions - - } /> - - - - } - /> - }> - - - }> - {settingsPage} - - } /> - } /> - {dynamicRoutes.map( - ({ Component, staticJSXContent, path, config: { props } }) => ( - } - > - {staticJSXContent} - - ), - )} - + + + + } + /> + } + > + {entityPage(entityTabOverrides)} + + + } + > + + {scaffolderFieldExtensions.map( + ({ scope, module, importName, Component }) => ( + + ), + )} + + scaffolderFieldExtensions + + } /> + + + + } + /> + }> + + + }> + {settingsPage} + + } /> + } /> + {dynamicRoutes.map( + ({ Component, staticJSXContent, path, config: { props } }) => ( + } + > + {staticJSXContent} + + ), + )} + + diff --git a/packages/app/src/components/Root/ApplicationListener.tsx b/packages/app/src/components/Root/ApplicationListener.tsx new file mode 100644 index 0000000000..94199a2f09 --- /dev/null +++ b/packages/app/src/components/Root/ApplicationListener.tsx @@ -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 ( + + + + ); + }); +}; diff --git a/packages/app/src/components/Root/ApplicationProvider.tsx b/packages/app/src/components/Root/ApplicationProvider.tsx new file mode 100644 index 0000000000..5bb5d604f9 --- /dev/null +++ b/packages/app/src/components/Root/ApplicationProvider.tsx @@ -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 ( + + {acc} + + ); + }, children); +}; diff --git a/plugins/dynamic-plugins-info/src/components/InternalPluginsMap.ts b/plugins/dynamic-plugins-info/src/components/InternalPluginsMap.ts index 370a467be2..2404a079ad 100644 --- a/plugins/dynamic-plugins-info/src/components/InternalPluginsMap.ts +++ b/plugins/dynamic-plugins-info/src/components/InternalPluginsMap.ts @@ -65,6 +65,8 @@ export const InternalPluginsMap: Record = { './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': diff --git a/yarn.lock b/yarn.lock index 439c4486f9..c896e87164 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12311,7 +12311,7 @@ __metadata: languageName: node linkType: hard -"@mui/icons-material@npm:5.16.14, @mui/icons-material@npm:^5.15.19, @mui/icons-material@npm:^5.16.4, @mui/icons-material@npm:^5.16.7": +"@mui/icons-material@npm:5.16.14, @mui/icons-material@npm:^5.15.17, @mui/icons-material@npm:^5.15.19, @mui/icons-material@npm:^5.16.4, @mui/icons-material@npm:^5.16.7": version: 5.16.14 resolution: "@mui/icons-material@npm:5.16.14" dependencies: @@ -16142,6 +16142,26 @@ __metadata: languageName: node linkType: hard +"@red-hat-developer-hub/backstage-plugin-global-floating-action-button@npm:0.0.6": + version: 0.0.6 + resolution: "@red-hat-developer-hub/backstage-plugin-global-floating-action-button@npm:0.0.6" + dependencies: + "@backstage/core-components": ^0.16.3 + "@backstage/core-plugin-api": ^1.10.3 + "@backstage/theme": ^0.6.3 + "@mui/icons-material": ^5.15.17 + "@mui/material": ^5.15.17 + "@mui/styles": 5.16.13 + "@scalprum/react-core": 0.9.3 + classnames: ^2.5.1 + react-use: ^17.2.4 + peerDependencies: + react: 16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: ^6.0.0 + checksum: 2c9f0046497b5f2f67f557078408bea951a897d0914aeb9a55b199c9a55dee094c0796438d23c4d092feb6b00ddf92dbd6494e5ff1b8a5285e7c31b928e40944 + languageName: node + linkType: hard + "@red-hat-developer-hub/backstage-plugin-global-header@npm:0.0.2": version: 0.0.2 resolution: "@red-hat-developer-hub/backstage-plugin-global-header@npm:0.0.2" @@ -40157,6 +40177,18 @@ __metadata: languageName: unknown linkType: soft +"red-hat-developer-hub-backstage-plugin-global-floating-action-button@workspace:dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button": + version: 0.0.0-use.local + resolution: "red-hat-developer-hub-backstage-plugin-global-floating-action-button@workspace:dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-floating-action-button" + dependencies: + "@backstage/cli": 0.29.6 + "@janus-idp/cli": 3.0.0 + "@mui/material": 5.16.14 + "@red-hat-developer-hub/backstage-plugin-global-floating-action-button": 0.0.6 + typescript: 5.7.3 + languageName: unknown + linkType: soft + "red-hat-developer-hub-backstage-plugin-global-header@workspace:dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header": version: 0.0.0-use.local resolution: "red-hat-developer-hub-backstage-plugin-global-header@workspace:dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-global-header"