From 721a6c8bf2f65b3b60bcf7d96d1b01279e5d78ca Mon Sep 17 00:00:00 2001 From: Scott Dickerson Date: Mon, 4 Mar 2024 21:33:54 -0500 Subject: [PATCH] :seedling: Setup branding to be configurable during the build (#1664) ## Summary Refactor and enhance branding capabilities. Now branding is included from a single directory that contains at least `strings.json`, `manifest.json`, and `favicon.ico`. Any other assets may be placed in the directory and will be copied to the bundled app. Running the build as normal should show no difference. Running the build with `BRANDING=./some-other-brand npm run start:dev` will try to use a branding from the specified directory (that is relative to the project's source root). See `BRANDING.md` for more details. Resolves: #1682 ## Details Branding changes: - Move Konveyor branding assets to a project top-level branding directory - Remove MTA branding assets - Remove profile/branding constants from `env` and client module - Embed branding strings and assets in the common module - `strings.json` is templated to allow the build to adjust asset URL path roots as necessary - `brandingAssetPath()` - server's index.html generation sources the template strings from the common module's branding strings - `HeaderApp` and `AppAboutModal` components support branding by using the `useBranding` hook - `BRANDING` as a relative path is computed from the project root - webpack build source branding assets directly from the common module - Unit tests, snapshots and jest configs updated as necessary Jest changes: - Use `react-i18next` mock from `client/__mocks__` as a more robust mock borrowed from react-i18n repos - Move `setupTests.ts` into `client/src/app/test-config` to keep jest test config code all in the same directory Related changes: - Upgrade rollup to v4, add new rollup plugins (copy, virtual) --------- Signed-off-by: Scott J Dickerson Co-authored-by: Ian Bolton Signed-off-by: Cherry Picker --- BRANDING.md | 151 +++++++ .../favicon.ico | Bin {client/public => branding/images}/logo.png | Bin .../public => branding/images}/logo192.png | Bin .../public => branding/images}/logo512.png | Bin .../images/masthead-logo.svg | 0 {client/public => branding}/manifest.json | 4 +- branding/strings.json | 21 + client/__mocks__/react-i18next.js | 68 +++ client/config/jest.config.ts | 5 +- client/config/webpack.common.ts | 31 +- client/config/webpack.dev.ts | 14 +- client/config/webpack.prod.ts | 11 +- client/public/index.html.ejs | 12 +- client/public/locales/en/translation.json | 4 +- client/public/mta-favicon.ico | Bin 15086 -> 0 bytes client/src/app/Constants.ts | 6 - client/src/app/hooks/useBranding.ts | 12 + client/src/app/images/avatar.svg | 33 -- .../app/images/konveyor-logo-white-text.png | Bin 10564 -> 0 bytes .../src/app/images/logo-navbar-patternfly.svg | 33 -- client/src/app/images/logo-navbar.svg | 1 - client/src/app/images/logo.svg | 13 - client/src/app/images/logoRedHat.svg | 1 - client/src/app/images/tackle.png | Bin 7948 -> 0 bytes .../layout/AppAboutModal/AppAboutModal.tsx | 77 ++-- .../tests/AppAboutModal.test.tsx | 2 +- .../__snapshots__/AppAboutModal.test.tsx.snap | 9 +- client/src/app/layout/HeaderApp/HeaderApp.tsx | 41 +- client/src/app/layout/HeaderApp/header.css | 7 - .../__snapshots__/HeaderApp.test.tsx.snap | 4 +- client/src/app/logo.svg | 1 - client/src/app/setupTests.ts | 50 --- client/src/app/test-config/setupTests.ts | 18 + common/package.json | 3 +- common/rollup.config.js | 41 +- common/src/branding-strings-stub.json | 21 + common/src/branding.ts | 48 ++ common/src/environment.ts | 11 +- common/src/index.ts | 1 + common/tsconfig.json | 11 +- package-lock.json | 419 ++++++++++++++++-- package.json | 14 +- server/src/index.js | 8 +- 44 files changed, 899 insertions(+), 307 deletions(-) create mode 100644 BRANDING.md rename client/public/konveyor-favicon.ico => branding/favicon.ico (100%) rename {client/public => branding/images}/logo.png (100%) rename {client/public => branding/images}/logo192.png (100%) rename {client/public => branding/images}/logo512.png (100%) rename client/src/app/images/Konveyor-white-logo.svg => branding/images/masthead-logo.svg (100%) rename {client/public => branding}/manifest.json (81%) create mode 100644 branding/strings.json create mode 100644 client/__mocks__/react-i18next.js delete mode 100644 client/public/mta-favicon.ico create mode 100644 client/src/app/hooks/useBranding.ts delete mode 100644 client/src/app/images/avatar.svg delete mode 100644 client/src/app/images/konveyor-logo-white-text.png delete mode 100644 client/src/app/images/logo-navbar-patternfly.svg delete mode 100644 client/src/app/images/logo-navbar.svg delete mode 100644 client/src/app/images/logo.svg delete mode 100644 client/src/app/images/logoRedHat.svg delete mode 100644 client/src/app/images/tackle.png delete mode 100644 client/src/app/logo.svg delete mode 100644 client/src/app/setupTests.ts create mode 100644 client/src/app/test-config/setupTests.ts create mode 100644 common/src/branding-strings-stub.json create mode 100644 common/src/branding.ts diff --git a/BRANDING.md b/BRANDING.md new file mode 100644 index 0000000000..b2043dd9a8 --- /dev/null +++ b/BRANDING.md @@ -0,0 +1,151 @@ +# Branding + +The UI supports static branding at build time. Dynamically switching brands is not +possible with the current implementation. + +## Summary + +Each of the project modules need to do some branding enablement. + +- `@konveyor-ui/common` pulls in the branding assets and packages the configuration, + strings and assets within the common package. The other modules pull branding + from the common module. + +- `@konveyor-ui/client` uses branding from the common package: + + - The location of `favicon.ico`, `manifest.json` and any other branding + assets that may be referenced in the `brandingStrings` are sourced from the + common package. + + - The `brandingStrings` are used by the dev-server runtime, to fill out the + `index.html` template. + + - The about modal and application masthead components use the branding strings + provided by the common module to display brand appropriate logos, titles and + about information. Since the common module provides all the information, it + is packaged directly into the app at build time. + +- `@konveyor-ui/server` uses the `brandingStrings` from the common package to fill + out the `index.html` template. + +## Providing alternate branding + +To provide an alternate branding to the build, specify the path to the branding assets +with the `BRANDING` environment variable. Relative paths in `BRANDING` are computed +from the project source root. + +Each brand requires the presence of at least the following files: + +- `strings.json` +- `favicon.ico` +- `manifest.json` + +With a file path of `/alt/custom-branding`, a build that uses an alternate branding +is run as: + +```sh +> BRANDING=/alt/custom-branding npm run build +``` + +The dev server can also be run this way. Since file watching of the branding assets +is not implemented in the common module's build watch mode, it may be necessary to +manually build the common module before running the dev server. When working on a +brand, it is useful to run the dev server like this: + +```sh +> export BRANDING=/alt/custom-branding +> npm run build -w common +> npm run start:dev +> unset BRANDING # when you don't want to use the custom branding path anymore +``` + +### File details + +#### strings.json + +The expected shape of `strings.json` is defined in [branding.ts](./common/src/branding.ts). + +The default version of the file is [branding/strings.json](./branding/strings.json). + +A minimal viable example of the file is: + +```json +{ + "application": { + "title": "Konveyor" + }, + "about": { + "displayName": "Konveyor" + }, + "masthead": {} +} +``` + +At build time, the json file is processed as an [ejs](https://ejs.co/) template. The +variable `brandingRoot` is provided as the relative root of the branding +assets within the build of the common module. Consider the location of `strings.json` +in your branding directory as the base `brandingRoot` when creating a new brand. + +For example, to properly reference a logo within this branding structure: + +``` + special-brand/ + images/ + masthead-logo.svg + about-logo.svg + strings.json +``` + +Use a url string like this: + +```json +{ + "about": { + "imageSrc": "<%= brandingRoot %>/images/about-logo.svg" + } +} +``` + +and in the output of `BRANDING=special-brand npm run build -w common`, the `imageSrc` +will be `branding/images/about-logo.svg` with all of the files in `special-branding/*` +copied to and available to the client and server modules from +`@konveyor-ui/common/branding/*`. + +#### favicon.ico + +A standard favorite icon file `favicon.ico` is required to be in the same directory +as `strings.json` + +#### manifest.json + +A standard [web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) +file `manifest.json` is required to be in the same directory as `strings.json`. + +## Technical details + +All branding strings and assets are pulled in to the common module. The client and +server modules access the branding from the common module build. + +The `common` module relies on rollup packaging to embed all of the brand for easy +use. The use of branding strings in `client` and `server` modules is straight forward. +Pulling in `strings.json` and providing the base path to the brand assets is a +more complicated. + +The `common` module provides the `brandingAssetPath()` function to let the build time +code find the root path to all brand assets. Webpack configuration files use this +function to source the favicon.ico, manifest.json and other brand assets to be copied +to the application bundle. + +The `brandingStrings` is typed and sourced from a json file. To pass typescript builds, +a stub json file needs to be available at transpile time. By using a typescript paths +of `@branding/strings.json`, the stub json is found at transpile time. The generated +javascript will still import the path alias. The +[virtual rollup plugin](https://github.com/rollup/plugins/tree/master/packages/virtual) +further transform the javascript output by replacing the `@branding/strings.json` import +with a dynamically built module containing the contents of the brand's `strings.json`. +The brand json becomes a virtual module embedded in the common module. + +A build for a custom brand will fail (1) if the expected files cannot be read, or (2) +if `strings.json` is not a valid JSON file. **Note:** The context of `stings.json` is +not currently validated. If something is missing or a url is malformed, it will only +be visible as a runtime error. diff --git a/client/public/konveyor-favicon.ico b/branding/favicon.ico similarity index 100% rename from client/public/konveyor-favicon.ico rename to branding/favicon.ico diff --git a/client/public/logo.png b/branding/images/logo.png similarity index 100% rename from client/public/logo.png rename to branding/images/logo.png diff --git a/client/public/logo192.png b/branding/images/logo192.png similarity index 100% rename from client/public/logo192.png rename to branding/images/logo192.png diff --git a/client/public/logo512.png b/branding/images/logo512.png similarity index 100% rename from client/public/logo512.png rename to branding/images/logo512.png diff --git a/client/src/app/images/Konveyor-white-logo.svg b/branding/images/masthead-logo.svg similarity index 100% rename from client/src/app/images/Konveyor-white-logo.svg rename to branding/images/masthead-logo.svg diff --git a/client/public/manifest.json b/branding/manifest.json similarity index 81% rename from client/public/manifest.json rename to branding/manifest.json index 2a98b57f08..eb8ffec956 100644 --- a/client/public/manifest.json +++ b/branding/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "tackle-ui", - "name": "Tackle UI", + "short_name": "konveyor-ui", + "name": "Konveyor UI", "icons": [ { "src": "favicon.ico", diff --git a/branding/strings.json b/branding/strings.json new file mode 100644 index 0000000000..116aa41ce5 --- /dev/null +++ b/branding/strings.json @@ -0,0 +1,21 @@ +{ + "application": { + "title": "Konveyor", + "name": "Konveyor Tackle UI", + "description": "Konveyor/Tackle UI" + }, + "about": { + "displayName": "Konveyor", + "imageSrc": "<%= brandingRoot %>/images/masthead-logo.svg", + "documentationUrl": "https://konveyor.github.io/konveyor/" + }, + "masthead": { + "leftBrand": { + "src": "<%= brandingRoot %>/images/masthead-logo.svg", + "alt": "brand", + "height": "60px" + }, + "leftTitle": null, + "rightBrand": null + } +} diff --git a/client/__mocks__/react-i18next.js b/client/__mocks__/react-i18next.js new file mode 100644 index 0000000000..60f67f05ea --- /dev/null +++ b/client/__mocks__/react-i18next.js @@ -0,0 +1,68 @@ +/* eslint-env node */ + +// Adapted from https://github.com/i18next/react-i18next/blob/master/example/test-jest/src/__mocks__/react-i18next.js +import React from "react"; +import * as reactI18next from "react-i18next"; + +const hasChildren = (node) => + node && (node.children || (node.props && node.props.children)); + +const getChildren = (node) => + node && node.children ? node.children : node.props && node.props.children; + +const renderNodes = (reactNodes) => { + if (typeof reactNodes === "string") { + return reactNodes; + } + + return Object.keys(reactNodes).map((key, i) => { + const child = reactNodes[key]; + const isElement = React.isValidElement(child); + + if (typeof child === "string") { + return child; + } + if (hasChildren(child)) { + const inner = renderNodes(getChildren(child)); + return React.cloneElement(child, { ...child.props, key: i }, inner); + } + if (typeof child === "object" && !isElement) { + return Object.keys(child).reduce( + (str, childKey) => `${str}${child[childKey]}`, + "" + ); + } + + return child; + }); +}; + +const useMock = [(k) => k, { changeLanguage: () => new Promise(() => {}) }]; +useMock.t = (k) => k; +useMock.i18n = { changeLanguage: () => new Promise(() => {}) }; + +module.exports = { + Trans: ({ children, i18nKey }) => + !children + ? i18nKey + : Array.isArray(children) + ? renderNodes(children) + : renderNodes([children]), + + Translation: ({ children }) => children((k) => k, { i18n: {} }), + + useTranslation: () => useMock, + + initReactI18next: { + type: "3rdParty", + init: () => {}, + }, + + // mock if needed + withTranslation: reactI18next.withTranslation, + I18nextProvider: reactI18next.I18nextProvider, + setDefaults: reactI18next.setDefaults, + getDefaults: reactI18next.getDefaults, + setI18n: reactI18next.setI18n, + getI18n: reactI18next.getI18n, +}; diff --git a/client/config/jest.config.ts b/client/config/jest.config.ts index 202a284ba7..6d683a6023 100644 --- a/client/config/jest.config.ts +++ b/client/config/jest.config.ts @@ -23,6 +23,9 @@ const config: JestConfigWithTsJest = { "@patternfly/react-icons/dist/esm/icons/": "/__mocks__/fileMock.js", + // other mocks + "react-i18next": "/__mocks__/react-i18next.js", + // match the paths in tsconfig.json "@app/(.*)": "/src/app/$1", "@assets/(.*)": @@ -44,7 +47,7 @@ const config: JestConfigWithTsJest = { }, // Code to set up the testing framework before each test file in the suite is executed - setupFilesAfterEnv: ["/src/app/setupTests.ts"], + setupFilesAfterEnv: ["/src/app/test-config/setupTests.ts"], }; export default config; diff --git a/client/config/webpack.common.ts b/client/config/webpack.common.ts index ffaa95c5ca..637b943652 100644 --- a/client/config/webpack.common.ts +++ b/client/config/webpack.common.ts @@ -1,15 +1,18 @@ import path from "path"; import { Configuration } from "webpack"; -// import CaseSensitivePathsWebpackPlugin from "case-sensitive-paths-webpack-plugin"; import CopyPlugin from "copy-webpack-plugin"; import Dotenv from "dotenv-webpack"; import { TsconfigPathsPlugin } from "tsconfig-paths-webpack-plugin"; import MonacoWebpackPlugin from "monaco-editor-webpack-plugin"; +import { brandingAssetPath } from "@konveyor-ui/common"; import { LANGUAGES_BY_FILE_EXTENSION } from "./monacoConstants"; -const BG_IMAGES_DIRNAME = "images"; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const brandingPath = brandingAssetPath(); +const manifestPath = path.resolve(brandingPath, "manifest.json"); + +const BG_IMAGES_DIRNAME = "images"; const config: Configuration = { entry: { @@ -150,22 +153,26 @@ const config: Configuration = { exports: "xmllint", }, }, - // For monaco-editor-webpack-plugin + { + test: /\.yaml$/, + use: "raw-loader", + }, + + // For monaco-editor-webpack-plugin ---> { test: /\.css$/, include: [pathTo("../../node_modules/monaco-editor")], use: ["style-loader", "css-loader"], }, - // For monaco-editor-webpack-plugin { test: /\.ttf$/, type: "asset/resource", }, + // <--- For monaco-editor-webpack-plugin ], }, plugins: [ - // new CaseSensitivePathsWebpackPlugin(), new Dotenv({ systemvars: true, silent: true, @@ -174,15 +181,19 @@ const config: Configuration = { patterns: [ { from: pathTo("../public/locales"), - to: pathTo("../dist/locales"), + to: "./locales/", }, { - from: pathTo("../public/manifest.json"), - to: pathTo("../dist/manifest.json"), + from: pathTo("../public/templates"), + to: "./templates/", }, { - from: pathTo("../public/templates"), - to: pathTo("../dist/templates"), + from: manifestPath, + to: ".", + }, + { + from: brandingPath, + to: "./branding/", }, ], }), diff --git a/client/config/webpack.dev.ts b/client/config/webpack.dev.ts index d935f8d63a..9c0c367e34 100644 --- a/client/config/webpack.dev.ts +++ b/client/config/webpack.dev.ts @@ -2,7 +2,6 @@ import path from "path"; import { mergeWithRules } from "webpack-merge"; import type { Configuration as WebpackConfiguration } from "webpack"; import type { Configuration as DevServerConfiguration } from "webpack-dev-server"; - import CopyPlugin from "copy-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; import ReactRefreshTypeScript from "react-refresh-typescript"; @@ -14,12 +13,14 @@ import { KONVEYOR_ENV, SERVER_ENV_KEYS, proxyMap, + brandingStrings, + brandingAssetPath, } from "@konveyor-ui/common"; import { stylePaths } from "./stylePaths"; import commonWebpackConfiguration from "./webpack.common"; -const brandType = KONVEYOR_ENV.PROFILE; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const faviconPath = path.resolve(brandingAssetPath(), "favicon.ico"); interface Configuration extends WebpackConfiguration { devServer?: DevServerConfiguration; @@ -75,10 +76,6 @@ const config: Configuration = mergeWithRules({ include: [...stylePaths], use: ["style-loader", "css-loader"], }, - { - test: /\.yaml$/, - use: "raw-loader", - }, ], }, @@ -96,15 +93,16 @@ const config: Configuration = mergeWithRules({ }, ], }), + // index.html generated at compile time to inject `_env` new HtmlWebpackPlugin({ filename: "index.html", template: pathTo("../public/index.html.ejs"), templateParameters: { _env: encodeEnv(KONVEYOR_ENV, SERVER_ENV_KEYS), - brandType, + branding: brandingStrings, }, - favicon: pathTo(`../public/${brandType}-favicon.ico`), + favicon: faviconPath, minify: { collapseWhitespace: false, keepClosingSlash: true, diff --git a/client/config/webpack.prod.ts b/client/config/webpack.prod.ts index 5b1f667e36..db3978e741 100644 --- a/client/config/webpack.prod.ts +++ b/client/config/webpack.prod.ts @@ -5,12 +5,12 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"; import CssMinimizerPlugin from "css-minimizer-webpack-plugin"; import HtmlWebpackPlugin from "html-webpack-plugin"; -import { KONVEYOR_ENV } from "@konveyor-ui/common"; +import { brandingAssetPath } from "@konveyor-ui/common"; import { stylePaths } from "./stylePaths"; import commonWebpackConfiguration from "./webpack.common"; -const brandType = KONVEYOR_ENV.PROFILE; const pathTo = (relativePath: string) => path.resolve(__dirname, relativePath); +const faviconPath = path.resolve(brandingAssetPath(), "favicon.ico"); const config = merge(commonWebpackConfiguration, { mode: "production", @@ -36,10 +36,6 @@ const config = merge(commonWebpackConfiguration, { include: [...stylePaths], use: [MiniCssExtractPlugin.loader, "css-loader"], }, - { - test: /\.yaml$/, - use: "raw-loader", - }, ], }, @@ -56,11 +52,12 @@ const config = merge(commonWebpackConfiguration, { new webpack.EnvironmentPlugin({ NODE_ENV: "production", }), + // index.html generated at runtime via the express server to inject `_env` new HtmlWebpackPlugin({ filename: "index.html.ejs", template: `!!raw-loader!${pathTo("../public/index.html.ejs")}`, - favicon: pathTo(`../public/${brandType}-favicon.ico`), + favicon: faviconPath, minify: { collapseWhitespace: false, keepClosingSlash: true, diff --git a/client/public/index.html.ejs b/client/public/index.html.ejs index 632b99ed8f..0db08e3428 100644 --- a/client/public/index.html.ejs +++ b/client/public/index.html.ejs @@ -1,15 +1,9 @@ - <% if (brandType == 'mta') { %> - Migration Toolkit for Applications - - - <% } else { %> - Konveyor - - - <% } %> + <%= branding.application.title %> + + diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 95593f0e53..42e84f648d 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -1,8 +1,8 @@ { "about": { "about": "About", - "bottom1": "{{brandType}} is a project within the", - "bottom2": "For more information, refer to", + "bottom1": "{{brandType}} is a project within the <2>Konveyor community.", + "bottom2": "For more information, refer to <1>{{brandType}} documentation.", "description": "{{brandType}} allows users to maintain their portfolio of applications with a full set of metadata and to assess their suitability for modernization leveraging a questionnaire based approach.", "iconLibrary": "The Icon Library used in this project is a derivative of the <2>Standard Icons library by <5>Red Hat, used under <8>CC BY 4.0", "introduction": "{{brandType}} is a collection of tools that supports large-scale application modernization and migration projects to Kubernetes." diff --git a/client/public/mta-favicon.ico b/client/public/mta-favicon.ico deleted file mode 100644 index 7fe9dd26e2733706420ebc55427ed228abd30980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 diff --git a/client/src/app/Constants.ts b/client/src/app/Constants.ts index 81954b6c0f..2633f1e29f 100644 --- a/client/src/app/Constants.ts +++ b/client/src/app/Constants.ts @@ -12,14 +12,8 @@ import { import { EffortEstimate, ProposedAction, Risk } from "@app/api/models"; import { ENV } from "./env"; -export enum BrandType { - Konveyor = "konveyor", - MTA = "mta", -} - export const isAuthRequired = ENV.AUTH_REQUIRED !== "false"; export const uploadLimit = ENV.UI_INGRESS_PROXY_BODY_SIZE || "500m"; -export const APP_BRAND = ENV.PROFILE as BrandType; export const isRWXSupported = ENV.RWX_SUPPORTED === "true"; export const DEFAULT_SELECT_MAX_HEIGHT = 200; diff --git a/client/src/app/hooks/useBranding.ts b/client/src/app/hooks/useBranding.ts new file mode 100644 index 0000000000..cb90e35112 --- /dev/null +++ b/client/src/app/hooks/useBranding.ts @@ -0,0 +1,12 @@ +import { BrandingStrings, brandingStrings } from "@konveyor-ui/common"; + +/** + * Wrap the branding strings in a hook so components access it in a standard + * React way instead of a direct import. This allows the branding implementation + * to change in future with a minimal amount of refactoring in existing components. + */ +export const useBranding = (): BrandingStrings => { + return brandingStrings; +}; + +export default useBranding; diff --git a/client/src/app/images/avatar.svg b/client/src/app/images/avatar.svg deleted file mode 100644 index 11c80b85ff..0000000000 --- a/client/src/app/images/avatar.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/src/app/images/konveyor-logo-white-text.png b/client/src/app/images/konveyor-logo-white-text.png deleted file mode 100644 index 7fb562747c9183b90c6b08acac7406d2127d5d13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10564 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 Ay#N3J diff --git a/client/src/app/images/logo-navbar-patternfly.svg b/client/src/app/images/logo-navbar-patternfly.svg deleted file mode 100644 index 232a493d1c..0000000000 --- a/client/src/app/images/logo-navbar-patternfly.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - PatternFly Logo - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/client/src/app/images/logo-navbar.svg b/client/src/app/images/logo-navbar.svg deleted file mode 100644 index 61bf32f4ff..0000000000 --- a/client/src/app/images/logo-navbar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/app/images/logo.svg b/client/src/app/images/logo.svg deleted file mode 100644 index 099049afb0..0000000000 --- a/client/src/app/images/logo.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/client/src/app/images/logoRedHat.svg b/client/src/app/images/logoRedHat.svg deleted file mode 100644 index 679f697999..0000000000 --- a/client/src/app/images/logoRedHat.svg +++ /dev/null @@ -1 +0,0 @@ -RedHat-Logo-A-Reverse \ No newline at end of file diff --git a/client/src/app/images/tackle.png b/client/src/app/images/tackle.png deleted file mode 100644 index 6e61e7a5a1f3af54d1227e4ebc6e01d146fe9b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7948 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 diff --git a/client/src/app/layout/AppAboutModal/AppAboutModal.tsx b/client/src/app/layout/AppAboutModal/AppAboutModal.tsx index d1ff977436..9e466a16e0 100644 --- a/client/src/app/layout/AppAboutModal/AppAboutModal.tsx +++ b/client/src/app/layout/AppAboutModal/AppAboutModal.tsx @@ -9,71 +9,74 @@ import { TextList, TextListItem, } from "@patternfly/react-core"; - -import konveyorBrandImage from "@app/images/Konveyor-white-logo.svg"; -import mtaBrandImage from "@app/images/logoRedHat.svg"; -import { APP_BRAND, BrandType } from "@app/Constants"; import { ENV } from "@app/env"; +import useBranding from "@app/hooks/useBranding"; export interface AppAboutModalProps { isOpen: boolean; onClose: () => void; } +const TRANSPARENT_1x1_GIF = + "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw== "; + export const AppAboutModal: React.FC = ({ isOpen, onClose, }) => { const { t } = useTranslation(); - const brandName = - APP_BRAND === BrandType.Konveyor - ? "Konveyor" - : "Migration Toolkit for Applications"; + const { about } = useBranding(); + return ( {t("about.about")} + - {t("about.introduction", { brandType: brandName })} + {t("about.introduction", { brandType: about.displayName })} + - {t("about.description", { brandType: brandName })} + {t("about.description", { brandType: about.displayName })} + - {t("about.bottom1", { brandType: brandName })}{" "} - - Konveyor community - - . + + {{ brandType: about.displayName }} is a project within the + + Konveyor community + + . + - - {t("about.bottom2")}{" "} - - {brandName} documentation + + {about.documentationUrl ? ( + + + For more information, refer to + + {{ brandType: about.displayName }} documentation + + . + - . - + ) : null} + The Icon Library used in this project is a derivative of the{" "} diff --git a/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx b/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx index db7d749b3e..6b173e1205 100644 --- a/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx +++ b/client/src/app/layout/AppAboutModal/tests/AppAboutModal.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { render } from "@app/test-config/test-utils"; import React from "react"; import { AppAboutModal } from "../AppAboutModal"; diff --git a/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap b/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap index d876d1c24f..d78b2a383f 100644 --- a/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap +++ b/client/src/app/layout/AppAboutModal/tests/__snapshots__/AppAboutModal.test.tsx.snap @@ -36,7 +36,7 @@ exports[`AppAboutModal 1`] = ` Logo
- about.bottom1 - + Konveyor + is a project within the - about.bottom2 - + For more information, refer to { + const { + masthead: { leftBrand, leftTitle, rightBrand }, + } = useBranding(); + const toolbar = ( @@ -69,16 +72,21 @@ export const HeaderApp: React.FC = () => { - {APP_BRAND === BrandType.MTA && ( + {rightBrand ? ( - Logo + - )} + ) : null} ); + return ( @@ -88,17 +96,22 @@ export const HeaderApp: React.FC = () => { - {APP_BRAND === BrandType.Konveyor ? ( + {leftBrand ? ( - ) : ( - - Migration Toolkit for Applications + ) : null} + {leftTitle ? ( + <Title + className="logo-pointer" + headingLevel={leftTitle?.heading ?? "h1"} + size={leftTitle?.size ?? "2xl"} + > + {leftTitle.text} - )} + ) : null} {toolbar} diff --git a/client/src/app/layout/HeaderApp/header.css b/client/src/app/layout/HeaderApp/header.css index 1585cdb0c4..4bda787c48 100644 --- a/client/src/app/layout/HeaderApp/header.css +++ b/client/src/app/layout/HeaderApp/header.css @@ -1,10 +1,3 @@ .logo-pointer { cursor: default !important; } -.pf-v5-c-page__header-brand-link { - all: unset !important; -} -.redhat-logo-style { - height: 30px; - vertical-align: middle; -} diff --git a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap index 880956053b..8517bcbd8c 100644 --- a/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap +++ b/client/src/app/layout/HeaderApp/tests/__snapshots__/HeaderApp.test.tsx.snap @@ -46,7 +46,7 @@ exports[`Test snapshot 1`] = ` brand @@ -170,7 +170,7 @@ exports[`Test snapshot 1`] = ` brand diff --git a/client/src/app/logo.svg b/client/src/app/logo.svg deleted file mode 100644 index 9dfc1c058c..0000000000 --- a/client/src/app/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/app/setupTests.ts b/client/src/app/setupTests.ts deleted file mode 100644 index 99dfb8bca1..0000000000 --- a/client/src/app/setupTests.ts +++ /dev/null @@ -1,50 +0,0 @@ -import "@testing-library/jest-dom"; - -let mockInitialized = false; - -jest.mock("@react-keycloak/web", () => { - const originalModule = jest.requireActual("@react-keycloak/web"); - return { - ...originalModule, - useKeycloak: () => [mockInitialized], - }; -}); - -jest.mock("react-i18next", () => ({ - Trans: ({ children }: { children: any }) => { - return children; - }, - useTranslation: () => { - return { - t: (str: any) => str, - i18n: { - changeLanguage: () => new Promise(() => {}), - }, - }; - }, -})); - -jest.mock("react-router-dom", () => ({ - ...jest.requireActual("react-router-dom"), - useLocation: () => ({ - pathname: "localhost:3000/example/path", - }), -})); - -jest.mock("react-i18next", () => ({ - Trans: ({ children }: { children: any }) => { - return children; - }, - useTranslation: () => { - return { - t: (str: any) => str, - i18n: { - changeLanguage: () => new Promise(() => {}), - }, - }; - }, - initReactI18next: { - type: "3rdParty", - init: jest.fn(), - }, -})); diff --git a/client/src/app/test-config/setupTests.ts b/client/src/app/test-config/setupTests.ts new file mode 100644 index 0000000000..0618b987c9 --- /dev/null +++ b/client/src/app/test-config/setupTests.ts @@ -0,0 +1,18 @@ +import "@testing-library/jest-dom"; + +const mockInitialized = false; + +jest.mock("@react-keycloak/web", () => { + const originalModule = jest.requireActual("@react-keycloak/web"); + return { + ...originalModule, + useKeycloak: () => [mockInitialized], + }; +}); + +jest.mock("react-router-dom", () => ({ + ...jest.requireActual("react-router-dom"), + useLocation: () => ({ + pathname: "localhost:3000/example/path", + }), +})); diff --git a/common/package.json b/common/package.json index fd763c7684..7292b10912 100644 --- a/common/package.json +++ b/common/package.json @@ -10,7 +10,8 @@ "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" - } + }, + "./package.json": "./package.json" }, "types": "./dist", "main": "./dist/index.cjs", diff --git a/common/rollup.config.js b/common/rollup.config.js index 8ca573c280..d6fbad60b2 100644 --- a/common/rollup.config.js +++ b/common/rollup.config.js @@ -1,5 +1,35 @@ +/* eslint-env node */ + +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { readFileSync } from "node:fs"; +import util from "node:util"; + +import copy from "rollup-plugin-copy"; import nodeResolve from "@rollup/plugin-node-resolve"; import typescript from "@rollup/plugin-typescript"; +import virtual from "@rollup/plugin-virtual"; +import ejs from "ejs"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const pathTo = (...relativePath) => path.resolve(__dirname, ...relativePath); + +const baseBrandingPath = process.env.BRANDING ?? "./branding"; +const brandingPath = pathTo("../", baseBrandingPath); +const jsonStrings = JSON.parse( + readFileSync(path.resolve(brandingPath, "./strings.json"), "utf8") +); +const stringModule = ejs.render( + ` + export const strings = ${util.inspect(jsonStrings)}; + export default strings; +`, + { + brandingRoot: "branding", + } +); + +console.log("Using branding assets from:", brandingPath); const config = { input: "src/index.ts", @@ -21,7 +51,16 @@ const config = { clearScreen: false, }, - plugins: [nodeResolve(), typescript()], + plugins: [ + copy({ + targets: [{ src: `${brandingPath}/**/*`, dest: "dist/branding" }], + }), + nodeResolve(), + typescript(), + virtual({ + "@branding/strings.json": stringModule, + }), + ], }; export default config; diff --git a/common/src/branding-strings-stub.json b/common/src/branding-strings-stub.json new file mode 100644 index 0000000000..8477bd9037 --- /dev/null +++ b/common/src/branding-strings-stub.json @@ -0,0 +1,21 @@ +{ + "application": { + "title": "Stub to allow package build to work", + "name": "", + "description": "" + }, + "about": { + "displayName": "", + "image": "", + "documentationUrl": "" + }, + "masthead": { + "leftBrand": { + "src": "", + "alt": "", + "height": "" + }, + "leftTitle": null, + "rightBrand": null + } +} diff --git a/common/src/branding.ts b/common/src/branding.ts new file mode 100644 index 0000000000..059051f76b --- /dev/null +++ b/common/src/branding.ts @@ -0,0 +1,48 @@ +export interface MastheadBrand { + src: string; + alt: string; + height: string; +} + +export interface MastheadTitle { + text: string; + heading?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + size?: "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl"; +} + +export interface BrandingStrings { + application: { + title: string; + name?: string; + description?: string; + }; + + about: { + displayName: string; + imageSrc?: string; + documentationUrl?: string; + }; + + masthead: { + leftBrand?: MastheadBrand; + leftTitle?: MastheadTitle; + rightBrand?: MastheadBrand; + }; +} + +// Note: Typescript will look at the `paths` definition to resolve this import +// to a stub JSON file. In the next rollup build step, that import will +// be replaced by the rollup virtual plugin with a dynamically generated +// JSON import with the actual branding information. +import * as stringsJson from "@branding/strings.json"; + +export const brandingStrings = + stringsJson.default as unknown as BrandingStrings; + +/** + * Return the `node_modules/` resolved path for the branding assets. + */ +export const brandingAssetPath = () => + require + .resolve("@konveyor-ui/common/package.json") + .replace(/(.)\/package.json$/, "$1") + "/dist/branding"; diff --git a/common/src/environment.ts b/common/src/environment.ts index 06309a33ba..060f2b3e94 100644 --- a/common/src/environment.ts +++ b/common/src/environment.ts @@ -25,9 +25,6 @@ export type KonveyorEnvType = { /** SSO / Keycloak client id */ KEYCLOAK_CLIENT_ID: string; - /** Branding to apply to the UI */ - PROFILE: "konveyor" | "mta"; - /** UI upload file size limit in megabytes (MB), suffixed with "m" */ UI_INGRESS_PROXY_BODY_SIZE: string; @@ -42,6 +39,9 @@ export type KonveyorEnvType = { /** Target URL for the UI server's `/hub` proxy */ TACKLE_HUB_URL?: string; + + /** Location of branding files (relative paths computed from the project source root) */ + BRANDING?: string; }; /** @@ -52,6 +52,7 @@ export const SERVER_ENV_KEYS = [ "PORT", "KEYCLOAK_SERVER_URL", "TACKLE_HUB_URL", + "BRANDING", ]; /** @@ -68,10 +69,10 @@ export const buildKonveyorEnv = ({ KEYCLOAK_REALM = "tackle", KEYCLOAK_CLIENT_ID = "tackle-ui", - PROFILE = "konveyor", UI_INGRESS_PROXY_BODY_SIZE = "500m", RWX_SUPPORTED = "true", TACKLE_HUB_URL, + BRANDING, }: Partial = {}): KonveyorEnvType => ({ NODE_ENV, PORT, @@ -83,10 +84,10 @@ export const buildKonveyorEnv = ({ KEYCLOAK_REALM, KEYCLOAK_CLIENT_ID, - PROFILE, UI_INGRESS_PROXY_BODY_SIZE, RWX_SUPPORTED, TACKLE_HUB_URL, + BRANDING, }); /** diff --git a/common/src/index.ts b/common/src/index.ts index 12f839c15f..fd048162a6 100644 --- a/common/src/index.ts +++ b/common/src/index.ts @@ -1,5 +1,6 @@ export * from "./environment.js"; export * from "./proxies.js"; +export * from "./branding.js"; /** * Return a base64 encoded JSON string containing the given `env` object. diff --git a/common/tsconfig.json b/common/tsconfig.json index e6785502ec..c65dfdab80 100644 --- a/common/tsconfig.json +++ b/common/tsconfig.json @@ -6,13 +6,18 @@ "compilerOptions": { "strict": true, "target": "es2020", - "module": "Node16", - "moduleResolution": "Node16", + "module": "node16", + "moduleResolution": "node16", "outDir": "./dist", "declaration": true, "declarationMap": true, "sourceMap": true, - "inlineSources": true + "inlineSources": true, + "resolveJsonModule": true, + + "paths": { + "@branding/strings.json": ["./src/branding-strings-stub.json"] + } } } diff --git a/package-lock.json b/package-lock.json index 6ed9531d8d..e6b4957ec2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,12 @@ "client" ], "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.3", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.1.0", - "@rollup/plugin-run": "^3.0.1", - "@rollup/plugin-typescript": "^11.1.2", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-run": "^3.0.2", + "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-virtual": "^3.0.2", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -41,7 +42,8 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^3.27.2", + "rollup": "^4.9.5", + "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "type-fest": "^3.13.0", @@ -1905,9 +1907,9 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.4.tgz", - "integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==", + "version": "25.0.7", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", + "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1915,13 +1917,13 @@ "estree-walker": "^2.0.2", "glob": "^8.0.3", "is-reference": "1.2.1", - "magic-string": "^0.27.0" + "magic-string": "^0.30.3" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.68.0||^3.0.0" + "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1930,18 +1932,18 @@ } }, "node_modules/@rollup/plugin-json": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", - "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^5.0.1" + "@rollup/pluginutils": "^5.1.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1950,9 +1952,9 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", - "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -1966,7 +1968,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" + "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1975,9 +1977,9 @@ } }, "node_modules/@rollup/plugin-run": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-run/-/plugin-run-3.0.1.tgz", - "integrity": "sha512-wbYR1Ahz8ohYnlyXzpBTwhGWfs+OO/uZMjgpDGr8AgnL/XfoTbO7BuNYY8ncR/j/1dhCJo+NDuTRkIeCxE434Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-run/-/plugin-run-3.0.2.tgz", + "integrity": "sha512-pgQcDA34u6C+8Yr0FSd2T7iN2UTQe8zJ+1pbceNJ9MkvGrN0sz4D6Mzg3eYkGrbV4zC7H5QvwlzC1GqH4PrSrg==", "dev": true, "dependencies": { "@types/node": "14.18.30" @@ -1986,7 +1988,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.0.0||^3.0.0" + "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -2001,19 +2003,19 @@ "dev": true }, "node_modules/@rollup/plugin-typescript": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz", - "integrity": "sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA==", + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", "dev": true, "dependencies": { - "@rollup/pluginutils": "^5.0.1", + "@rollup/pluginutils": "^5.1.0", "resolve": "^1.22.1" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.14.0||^3.0.0", + "rollup": "^2.14.0||^3.0.0||^4.0.0", "tslib": "*", "typescript": ">=3.7.0" }, @@ -2026,10 +2028,27 @@ } } }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", - "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -2040,7 +2059,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -2048,6 +2067,175 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz", + "integrity": "sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz", + "integrity": "sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz", + "integrity": "sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz", + "integrity": "sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz", + "integrity": "sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz", + "integrity": "sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz", + "integrity": "sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz", + "integrity": "sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz", + "integrity": "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz", + "integrity": "sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz", + "integrity": "sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz", + "integrity": "sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz", + "integrity": "sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2546,9 +2734,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/express": { @@ -2581,6 +2769,25 @@ "integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==", "dev": true }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -2706,6 +2913,12 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "devOptional": true }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -11040,12 +11253,12 @@ } }, "node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { "node": ">=12" @@ -14128,21 +14341,139 @@ } }, "node_modules/rollup": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.1.tgz", - "integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz", + "integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.5", + "@rollup/rollup-android-arm64": "4.9.5", + "@rollup/rollup-darwin-arm64": "4.9.5", + "@rollup/rollup-darwin-x64": "4.9.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.5", + "@rollup/rollup-linux-arm64-gnu": "4.9.5", + "@rollup/rollup-linux-arm64-musl": "4.9.5", + "@rollup/rollup-linux-riscv64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-musl": "4.9.5", + "@rollup/rollup-win32-arm64-msvc": "4.9.5", + "@rollup/rollup-win32-ia32-msvc": "4.9.5", + "@rollup/rollup-win32-x64-msvc": "4.9.5", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "node_modules/rollup-plugin-copy/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup-plugin-copy/node_modules/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", diff --git a/package.json b/package.json index 574a135ae3..e65f3f6fa6 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,12 @@ "npm": ">=9.5.0" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.3", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.1.0", - "@rollup/plugin-run": "^3.0.1", - "@rollup/plugin-typescript": "^11.1.2", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-run": "^3.0.2", + "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-virtual": "^3.0.2", "@tanstack/eslint-plugin-query": "^4.34.1", "@types/jest": "^29.5.4", "@types/node": "^18.14.2", @@ -65,7 +66,8 @@ "lint-staged": "^14.0.1", "prettier": "^3.0.2", "rimraf": "^4.4.1", - "rollup": "^3.27.2", + "rollup": "^4.9.5", + "rollup-plugin-copy": "^3.5.0", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "type-fest": "^3.13.0", diff --git a/server/src/index.js b/server/src/index.js index 44081efc1a..161a59231d 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -1,7 +1,7 @@ /* eslint-env node */ -import path from "path"; -import { fileURLToPath } from "url"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; import express from "express"; import ejs from "ejs"; @@ -14,12 +14,12 @@ import { KONVEYOR_ENV, SERVER_ENV_KEYS, proxyMap, + brandingStrings, } from "@konveyor-ui/common"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); const pathToClientDist = path.join(__dirname, "../../client/dist"); -const brandType = KONVEYOR_ENV.PROFILE; const port = parseInt(KONVEYOR_ENV.PORT, 10) || 8080; const app = express(); @@ -48,7 +48,7 @@ app.get("*", (_, res) => { } else { res.render("index.html.ejs", { _env: encodeEnv(KONVEYOR_ENV, SERVER_ENV_KEYS), - brandType, + branding: brandingStrings, }); } });