diff --git a/clients/ui/frontend/.env b/clients/ui/frontend/.env new file mode 100644 index 00000000..39fbc83c --- /dev/null +++ b/clients/ui/frontend/.env @@ -0,0 +1,9 @@ +IS_PROJECT_ROOT_DIR=false +PORT=${FRONTEND_PORT} + +########## Change the following three variables to customize the Dashboard ########## +LOGO=logo-light-theme.svg +LOGO_DARK=logo-dark-theme.svg +FAVICON=favicon.ico +PRODUCT_NAME=Model Registry + diff --git a/clients/ui/frontend/.eslintrc b/clients/ui/frontend/.eslintrc.cjs similarity index 99% rename from clients/ui/frontend/.eslintrc rename to clients/ui/frontend/.eslintrc.cjs index 0ef2cf88..e366d0a9 100644 --- a/clients/ui/frontend/.eslintrc +++ b/clients/ui/frontend/.eslintrc.cjs @@ -1,4 +1,4 @@ -{ +module.exports = { "parser": "@typescript-eslint/parser", "env": { "browser": true, @@ -11,7 +11,7 @@ "js": true, "useJSXTextNode": true, "project": "./tsconfig.json", - "tsconfigRootDir": "." + "tsconfigRootDir": __dirname }, // includes the typescript specific rules found here: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules "plugins": [ diff --git a/clients/ui/frontend/.gitignore b/clients/ui/frontend/.gitignore index 4731abfe..f53c5d88 100644 --- a/clients/ui/frontend/.gitignore +++ b/clients/ui/frontend/.gitignore @@ -5,4 +5,4 @@ yarn.lock stats.json coverage .idea -.env +public-cypress diff --git a/clients/ui/frontend/config/dotenv.js b/clients/ui/frontend/config/dotenv.js new file mode 100644 index 00000000..c8a64d33 --- /dev/null +++ b/clients/ui/frontend/config/dotenv.js @@ -0,0 +1,177 @@ +const fs = require('fs'); +const path = require('path'); +const dotenv = require('dotenv'); +const dotenvExpand = require('dotenv-expand'); +const Dotenv = require('dotenv-webpack'); + +/** + * Determine if the project is standalone or nested. + * + * @param {string} directory + * @returns {boolean} + */ +const getProjectIsRootDir = (directory) => { + const dotenvLocalFile = path.resolve(directory, '.env.local'); + const dotenvFile = path.resolve(directory, '.env'); + let localIsRoot; + let isRoot; + + if (fs.existsSync(dotenvLocalFile)) { + const { IS_PROJECT_ROOT_DIR: DOTENV_LOCAL_ROOT } = dotenv.parse( + fs.readFileSync(dotenvLocalFile), + ); + localIsRoot = DOTENV_LOCAL_ROOT; + } + + if (fs.existsSync(dotenvFile)) { + const { IS_PROJECT_ROOT_DIR: DOTENV_ROOT } = dotenv.parse(fs.readFileSync(dotenvFile)); + isRoot = DOTENV_ROOT; + } + + return localIsRoot !== undefined ? localIsRoot !== 'false' : isRoot !== 'false'; +}; + +/** + * Return tsconfig compilerOptions. + * + * @param {string} directory + * @returns {object} + */ +const getTsCompilerOptions = (directory) => { + const tsconfigFile = path.resolve(directory, './tsconfig.json'); + let tsCompilerOptions = {}; + + if (fs.existsSync(tsconfigFile)) { + const { compilerOptions = { outDir: './dist', baseUrl: './src' } } = require(tsconfigFile); + tsCompilerOptions = compilerOptions; + } + + return tsCompilerOptions; +}; + +/** + * Setup a webpack dotenv plugin config. + * + * @param {string} path + * @returns {*} + */ +const setupWebpackDotenvFile = (path) => { + const settings = { + systemvars: true, + silent: true, + }; + + if (path) { + settings.path = path; + } + + return new Dotenv(settings); +}; + +/** + * Setup multiple webpack dotenv file parameters. + * + * @param {string} directory + * @param {string} env + * @param {boolean} isRoot + * @returns {Array} + */ +const setupWebpackDotenvFilesForEnv = ({ directory, env, isRoot = true }) => { + const dotenvWebpackSettings = []; + + if (env) { + dotenvWebpackSettings.push( + setupWebpackDotenvFile(path.resolve(directory, `.env.${env}.local`)), + ); + dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, `.env.${env}`))); + } + + dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, '.env.local'))); + dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, '.env'))); + + if (!isRoot) { + if (env) { + dotenvWebpackSettings.push( + setupWebpackDotenvFile(path.resolve(directory, '..', `.env.${env}.local`)), + ); + dotenvWebpackSettings.push( + setupWebpackDotenvFile(path.resolve(directory, '..', `.env.${env}`)), + ); + } + + dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, '..', '.env.local'))); + dotenvWebpackSettings.push(setupWebpackDotenvFile(path.resolve(directory, '..', '.env'))); + } + + return dotenvWebpackSettings; +}; + +/** + * Setup, and access, a dotenv file and the related set of parameters. + * + * @param {string} path + * @returns {*} + */ +const setupDotenvFile = (path) => { + const dotenvInitial = dotenv.config({ path }); + dotenvExpand(dotenvInitial); +}; + +/** + * Setup and access local and specific dotenv file parameters. + * + * @param {string} env + */ +const setupDotenvFilesForEnv = ({ env }) => { + const RELATIVE_DIRNAME = path.resolve(__dirname, '..'); + const IS_ROOT = getProjectIsRootDir(RELATIVE_DIRNAME); + const { baseUrl: TS_BASE_URL, outDir: TS_OUT_DIR } = getTsCompilerOptions(RELATIVE_DIRNAME); + + if (!IS_ROOT) { + if (env) { + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '..', `.env.${env}.local`)); + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '..', `.env.${env}`)); + } + + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '..', '.env.local')); + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '..', '.env')); + } + + if (env) { + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, `.env.${env}.local`)); + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, `.env.${env}`)); + } + + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '.env.local')); + setupDotenvFile(path.resolve(RELATIVE_DIRNAME, '.env')); + + const IMAGES_DIRNAME = process.env.IMAGES_DIRNAME || 'images'; + const PUBLIC_PATH = process.env.PUBLIC_PATH || '/'; + const SRC_DIR = path.resolve(RELATIVE_DIRNAME, process.env.SRC_DIR || TS_BASE_URL || 'src'); + const COMMON_DIR = path.resolve(RELATIVE_DIRNAME, process.env.COMMON_DIR || '../common'); + const DIST_DIR = path.resolve(RELATIVE_DIRNAME, process.env.DIST_DIR || TS_OUT_DIR || 'public'); + const HOST = process.env.HOST || 'localhost'; + const PORT = process.env.PORT || '9000'; + const PROXY_PROTOCOL = process.env.PROXY_PROTOCOL || 'http'; + const PROXY_HOST = process.env.PROXY_HOST || 'localhost'; + const PROXY_PORT = process.env.PROXY_PORT || process.env.PORT || 4000; + const DEV_MODE = process.env.DEV_MODE || undefined; + const OUTPUT_ONLY = process.env._OUTPUT_ONLY === 'true'; + + process.env._RELATIVE_DIRNAME = RELATIVE_DIRNAME; + process.env._UI_IS_PROJECT_ROOT_DIR = IS_ROOT; + process.env._IMAGES_DIRNAME = IMAGES_DIRNAME; + process.env._PUBLIC_PATH = PUBLIC_PATH; + process.env._SRC_DIR = SRC_DIR; + process.env._COMMON_DIR = COMMON_DIR; + process.env._DIST_DIR = DIST_DIR; + process.env._HOST = HOST; + process.env._PORT = PORT; + process.env._PROXY_PROTOCOL = PROXY_PROTOCOL; + process.env._PROXY_HOST = PROXY_HOST; + process.env._PROXY_PORT = PROXY_PORT; + process.env._OUTPUT_ONLY = OUTPUT_ONLY; + process.env._DEV_MODE = DEV_MODE; +}; + +module.exports = { setupWebpackDotenvFilesForEnv, setupDotenvFilesForEnv }; diff --git a/clients/ui/frontend/config/webpack.common.js b/clients/ui/frontend/config/webpack.common.js index 6da6aa23..8b8a000e 100644 --- a/clients/ui/frontend/config/webpack.common.js +++ b/clients/ui/frontend/config/webpack.common.js @@ -1,40 +1,68 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const Dotenv = require('dotenv-webpack'); -const ASSET_PATH = process.env.ASSET_PATH || '/'; -const IMAGES_DIRNAME = 'images'; -const relativeDir = path.resolve(__dirname, '..'); +const { setupWebpackDotenvFilesForEnv } = require('./dotenv'); + +const RELATIVE_DIRNAME = process.env._RELATIVE_DIRNAME; +const IS_PROJECT_ROOT_DIR = process.env._IS_PROJECT_ROOT_DIR; +const IMAGES_DIRNAME = process.env._IMAGES_DIRNAME; +const PUBLIC_PATH = process.env._PUBLIC_PATH; +const SRC_DIR = process.env._SRC_DIR; +const COMMON_DIR = process.env._COMMON_DIR; +const DIST_DIR = process.env._DIST_DIR; +const OUTPUT_ONLY = process.env._OUTPUT_ONLY; +const FAVICON = process.env.FAVICON; +const PRODUCT_NAME = process.env.PRODUCT_NAME; +const COVERAGE = process.env.COVERAGE; + +if (OUTPUT_ONLY !== 'true') { + console.info( + `\nPrepping files...\n SRC DIR: ${SRC_DIR}\n OUTPUT DIR: ${DIST_DIR}\n PUBLIC PATH: ${PUBLIC_PATH}\n`, + ); + if (COVERAGE === 'true') { + console.info('\nAdding code coverage instrumentation.\n'); + } +} + module.exports = (env) => { return { + entry: { + app: path.join(SRC_DIR, 'index.tsx'), + }, module: { rules: [ { - test: /\.(tsx|ts|jsx)?$/, + test: /\.(tsx|ts|jsx|js)?$/, + exclude: [/node_modules/, /__tests__/, /__mocks__/], + include: [SRC_DIR, COMMON_DIR], use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - experimentalWatchApi: true - } - } - ] + COVERAGE === 'true' && '@jsdevtools/coverage-istanbul-loader', + env === 'development' + ? { loader: 'swc-loader' } + : { + loader: 'ts-loader', + options: { + transpileOnly: true, + }, + }, + ], }, { test: /\.(svg|ttf|eot|woff|woff2)$/, - type: 'asset/resource', // only process modules with this loader // if they live under a 'fonts' or 'pficon' directory include: [ - path.resolve(relativeDir, 'node_modules/patternfly/dist/fonts'), - path.resolve(relativeDir, 'node_modules/@patternfly/react-core/dist/styles/assets/fonts'), - path.resolve(relativeDir, 'node_modules/@patternfly/react-core/dist/styles/assets/pficon'), - path.resolve(relativeDir, 'node_modules/@patternfly/patternfly/assets/fonts'), - path.resolve(relativeDir, 'node_modules/@patternfly/patternfly/assets/pficon') + path.resolve(RELATIVE_DIRNAME, 'node_modules/patternfly/dist/fonts'), + path.resolve( + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-core/dist/styles/assets/fonts', + ), + path.resolve( + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-core/dist/styles/assets/pficon', + ), + path.resolve(RELATIVE_DIRNAME, 'node_modules/@patternfly/patternfly/assets/fonts'), + path.resolve(RELATIVE_DIRNAME, 'node_modules/@patternfly/patternfly/assets/pficon'), ], use: { loader: 'file-loader', @@ -89,34 +117,41 @@ module.exports = (env) => { { test: /\.(jpg|jpeg|png|gif)$/i, include: [ - path.resolve(relativeDir, 'src'), - path.resolve(relativeDir, 'node_modules/patternfly'), - path.resolve(relativeDir, 'node_modules/@patternfly/patternfly/assets/images'), - path.resolve(relativeDir, 'node_modules/@patternfly/react-styles/css/assets/images'), - path.resolve(relativeDir, 'node_modules/@patternfly/react-core/dist/styles/assets/images'), + SRC_DIR, + COMMON_DIR, + path.resolve(RELATIVE_DIRNAME, 'node_modules/patternfly'), + path.resolve(RELATIVE_DIRNAME, 'node_modules/@patternfly/patternfly/assets/images'), path.resolve( - relativeDir, - 'node_modules/@patternfly/react-core/node_modules/@patternfly/react-styles/css/assets/images' + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-styles/css/assets/images', ), path.resolve( - relativeDir, - 'node_modules/@patternfly/react-table/node_modules/@patternfly/react-styles/css/assets/images' + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-core/dist/styles/assets/images', ), path.resolve( - relativeDir, - 'node_modules/@patternfly/react-inline-edit-extension/node_modules/@patternfly/react-styles/css/assets/images' - ) + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-core/node_modules/@patternfly/react-styles/css/assets/images', + ), + path.resolve( + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-table/node_modules/@patternfly/react-styles/css/assets/images', + ), + path.resolve( + RELATIVE_DIRNAME, + 'node_modules/@patternfly/react-inline-edit-extension/node_modules/@patternfly/react-styles/css/assets/images', + ), ], - type: 'asset/inline', use: [ { + loader: 'url-loader', options: { limit: 5000, outputPath: 'images', - name: '[name].[ext]' - } - } - ] + name: '[name].[ext]', + }, + }, + ], }, { test: /\.s[ac]ss$/i, @@ -128,35 +163,75 @@ module.exports = (env) => { // Compiles Sass to CSS 'sass-loader', ], - } - ] + }, + { + test: /\.ya?ml$/, + use: 'js-yaml-loader', + }, + ], }, output: { filename: '[name].bundle.js', - path: path.resolve(relativeDir, 'dist'), - publicPath: ASSET_PATH + path: DIST_DIR, + publicPath: PUBLIC_PATH, }, plugins: [ - new HtmlWebpackPlugin({ - template: path.resolve(relativeDir, 'src', 'index.html') + ...setupWebpackDotenvFilesForEnv({ + directory: RELATIVE_DIRNAME, + isRoot: IS_PROJECT_ROOT_DIR, }), - new Dotenv({ - systemvars: true, - silent: true + new HtmlWebpackPlugin({ + template: path.join(SRC_DIR, 'index.html'), + title: PRODUCT_NAME, + favicon: path.join(SRC_DIR, 'images', FAVICON), }), new CopyPlugin({ - patterns: [{ from: './src/images', to: 'images' }] - }) + patterns: [ + { + from: path.join(SRC_DIR, 'locales'), + to: path.join(DIST_DIR, 'locales'), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'favicons'), + to: path.join(DIST_DIR, 'favicons'), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'images'), + to: path.join(DIST_DIR, 'images'), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'favicon.ico'), + to: path.join(DIST_DIR), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'favicon.png'), + to: path.join(DIST_DIR), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'manifest.json'), + to: path.join(DIST_DIR), + noErrorOnMissing: true, + }, + { + from: path.join(SRC_DIR, 'robots.txt'), + to: path.join(DIST_DIR), + noErrorOnMissing: true, + }, + ], + }), ], resolve: { extensions: ['.js', '.ts', '.tsx', '.jsx'], - plugins: [ - new TsconfigPathsPlugin({ - configFile: path.resolve(relativeDir, './tsconfig.json') - }) - ], + alias: { + '~': path.resolve(SRC_DIR), + }, symlinks: false, - cacheWithContext: false - } + cacheWithContext: false, + }, }; }; diff --git a/clients/ui/frontend/config/webpack.dev.js b/clients/ui/frontend/config/webpack.dev.js index b2198a83..89d98025 100644 --- a/clients/ui/frontend/config/webpack.dev.js +++ b/clients/ui/frontend/config/webpack.dev.js @@ -1,48 +1,100 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - +const { execSync } = require('child_process'); const path = require('path'); const { merge } = require('webpack-merge'); -const common = require('./webpack.common.js'); -const { stylePaths } = require('./stylePaths'); -const HOST = process.env.HOST || 'localhost'; -const PORT = process.env.PORT || '9000'; -const PROXY_HOST = process.env.PROXY_HOST || 'localhost'; -const PROXY_PORT = process.env.PROXY_PORT || '4000'; -const PROXY_PROTOCOL = process.env.PROXY_PROTOCOL || 'http:'; -const relativeDir = path.resolve(__dirname, '..'); +const { setupWebpackDotenvFilesForEnv, setupDotenvFilesForEnv } = require('./dotenv'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +const SpeedMeasurePlugin = require('speed-measure-webpack-plugin'); -module.exports = merge(common('development'), { - mode: 'development', - devtool: 'eval-source-map', - devServer: { - host: HOST, - port: PORT, - historyApiFallback: true, - static: { - directory: path.resolve(relativeDir, 'dist'), - }, - client: { - overlay: true, +const smp = new SpeedMeasurePlugin({ disable: !process.env.MEASURE }); + +setupDotenvFilesForEnv({ env: 'development' }); +const webpackCommon = require('./webpack.common.js'); + +const RELATIVE_DIRNAME = process.env._RELATIVE_DIRNAME; +const IS_PROJECT_ROOT_DIR = process.env._IS_PROJECT_ROOT_DIR; +const SRC_DIR = process.env._SRC_DIR; +const COMMON_DIR = process.env._COMMON_DIR; +const DIST_DIR = process.env._DIST_DIR; +const HOST = process.env._HOST; +const PORT = process.env._PORT; +const PROXY_PROTOCOL = process.env._PROXY_PROTOCOL; +const PROXY_HOST = process.env._PROXY_HOST; +const PROXY_PORT = process.env._PROXY_PORT; + +module.exports = smp.wrap( + merge( + { + plugins: [ + ...setupWebpackDotenvFilesForEnv({ + directory: RELATIVE_DIRNAME, + env: 'development', + isRoot: IS_PROJECT_ROOT_DIR, + }), + ], }, - proxy: [ - { - context: ["/api"], - target: { - host: PROXY_HOST, - protocol: PROXY_PROTOCOL, - port: PROXY_PORT, + webpackCommon('development'), + { + mode: 'development', + devtool: 'eval-source-map', + optimization: { + runtimeChunk: 'single', + removeEmptyChunks: true, + }, + devServer: { + host: HOST, + port: PORT, + compress: true, + historyApiFallback: true, + hot: true, + open: false, + proxy: [ + { + context: ["/api"], + target: { + host: PROXY_HOST, + protocol: PROXY_PROTOCOL, + port: PROXY_PORT, + }, + changeOrigin: true, + }, + ], + devMiddleware: { + stats: 'errors-only', + }, + client: { + overlay: false, + }, + static: { + directory: DIST_DIR, + }, + onListening: (devServer) => { + if (devServer) { + console.log( + `\x1b[32m✓ Dashboard available at: \x1b[4mhttp://localhost:${ + devServer.server.address().port + }\x1b[0m`, + ); + } }, - changeOrigin: true, }, - ], - }, - module: { - rules: [ - { - test: /\.css$/, - include: [...stylePaths], - use: ['style-loader', 'css-loader'], + module: { + rules: [ + { + test: /\.css$/, + include: [ + SRC_DIR, + COMMON_DIR, + path.resolve(RELATIVE_DIRNAME, 'node_modules/@patternfly'), + ], + use: ['style-loader', 'css-loader'], + }, + ], }, - ], - }, -}); + plugins: [ + new ForkTsCheckerWebpackPlugin(), + new ReactRefreshWebpackPlugin({ overlay: false }), + ], + }, + ), +); diff --git a/clients/ui/frontend/config/webpack.prod.js b/clients/ui/frontend/config/webpack.prod.js index 906e2dc4..a14ef40f 100644 --- a/clients/ui/frontend/config/webpack.prod.js +++ b/clients/ui/frontend/config/webpack.prod.js @@ -1,38 +1,61 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - +const path = require('path'); const { merge } = require('webpack-merge'); -const common = require('./webpack.common.js'); -const { stylePaths } = require('./stylePaths'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const TerserJSPlugin = require('terser-webpack-plugin'); +const { setupWebpackDotenvFilesForEnv, setupDotenvFilesForEnv } = require('./dotenv'); + +setupDotenvFilesForEnv({ env: 'production' }); +const webpackCommon = require('./webpack.common.js'); + +const RELATIVE_DIRNAME = process.env._RELATIVE_DIRNAME; +const IS_PROJECT_ROOT_DIR = process.env._IS_PROJECT_ROOT_DIR; +const SRC_DIR = process.env._SRC_DIR; +const COMMON_DIR = process.env._COMMON_DIR; +const DIST_DIR = process.env._DIST_DIR; +const OUTPUT_ONLY = process.env._OUTPUT_ONLY; -module.exports = merge(common('production'), { - mode: 'production', - devtool: 'source-map', - optimization: { - minimizer: [ - new TerserJSPlugin({}), - new CssMinimizerPlugin({ - minimizerOptions: { - preset: ['default', { mergeLonghand: false }] - } - }) - ] +if (OUTPUT_ONLY !== 'true') { + console.info(`Cleaning OUTPUT DIR...\n ${DIST_DIR}\n`); +} + +module.exports = merge( + { + plugins: [ + ...setupWebpackDotenvFilesForEnv({ + directory: RELATIVE_DIRNAME, + env: 'production', + isRoot: IS_PROJECT_ROOT_DIR, + }), + ], + }, + webpackCommon('production'), + { + mode: 'production', + devtool: 'source-map', + optimization: { + minimize: true, + minimizer: [new TerserJSPlugin(), new CssMinimizerPlugin()], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + chunkFilename: '[name].bundle.css', + ignoreOrder: true, + }), + ], + module: { + rules: [ + { + test: /\.css$/, + include: [ + SRC_DIR, + COMMON_DIR, + path.resolve(RELATIVE_DIRNAME, 'node_modules/@patternfly'), + ], + use: [MiniCssExtractPlugin.loader, 'css-loader'], + }, + ], + }, }, - plugins: [ - new MiniCssExtractPlugin({ - filename: '[name].css', - chunkFilename: '[name].bundle.css' - }) - ], - module: { - rules: [ - { - test: /\.css$/, - include: [...stylePaths], - use: [MiniCssExtractPlugin.loader, 'css-loader'] - } - ] - } -}); +); diff --git a/clients/ui/frontend/package-lock.json b/clients/ui/frontend/package-lock.json index ee0bf564..503b8b2c 100644 --- a/clients/ui/frontend/package-lock.json +++ b/clients/ui/frontend/package-lock.json @@ -11,13 +11,14 @@ "dependencies": { "@emotion/react": "^11.13.5", "@emotion/styled": "^11.13.5", + "@patternfly/patternfly": "^6.0.0", "@patternfly/react-core": "6.0.0", "@patternfly/react-icons": "6.0.0", "@patternfly/react-styles": "6.0.0", "@patternfly/react-table": "6.0.0", "@patternfly/react-templates": "6.0.0", "classnames": "^2.2.6", - "dompurify": "^3.2.0", + "dompurify": "^2.2.6", "lodash-es": "^4.17.15", "npm-run-all": "^4.1.5", "react": "^18", @@ -34,13 +35,15 @@ "@mui/icons-material": "^6.1.10", "@mui/material": "^6.1.7", "@mui/types": "^7.2.17", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", + "@swc/core": "^1.9.1", "@testing-library/cypress": "^10.0.1", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.2", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "14.5.2", "@types/classnames": "^2.3.1", - "@types/dompurify": "^3.0.5", + "@types/dompurify": "^2.2.6", "@types/jest": "^29.5.13", "@types/lodash-es": "^4.17.8", "@types/react-dom": "^18.3.1", @@ -56,9 +59,12 @@ "cypress-high-resolution": "^1.0.0", "cypress-mochawesome-reporter": "^3.8.2", "cypress-multi-reporters": "^2.0.4", - "dotenv": "^16.4.5", - "dotenv-webpack": "^8.1.0", + "dotenv": "^8.2.0", + "dotenv-expand": "^5.1.0", + "dotenv-webpack": "^6.0.0", "expect": "^29.7.0", + "file-loader": "^6.1.1", + "fork-ts-checker-webpack-plugin": "^9.0.2", "html-webpack-plugin": "^5.6.3", "imagemin": "^9.0.0", "jest": "^29.7.0", @@ -69,13 +75,16 @@ "prettier": "^3.3.3", "prop-types": "^15.8.1", "raw-loader": "^4.0.2", + "react-refresh": "^0.14.2", "react-router-dom": "^7.0.2", "regenerator-runtime": "^0.14.1", - "rimraf": "^6.0.1", - "sass-loader": "^16.0.1", + "sass": "^1.56.2", + "sass-loader": "^13.2.0", "serve": "^14.2.4", - "style-loader": "^4.0.0", - "svg-url-loader": "^8.0.0", + "speed-measure-webpack-plugin": "^1.5.0", + "style-loader": "^2.0.0", + "svg-url-loader": "^6.0.0", + "swc-loader": "^0.2.6", "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.2.5", "ts-loader": "^9.5.1", @@ -83,7 +92,7 @@ "tslib": "^2.7.0", "typescript": "^5.7.2", "url-loader": "^4.1.1", - "webpack": "^5.95.0", + "webpack": "^5.96.1", "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.1.0", @@ -2446,102 +2455,6 @@ "license": "BSD-3-Clause", "optional": true }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3453,6 +3366,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -3492,6 +3406,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3512,6 +3427,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3532,6 +3448,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3552,6 +3469,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3572,6 +3490,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3592,6 +3511,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3612,6 +3532,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3632,6 +3553,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3652,6 +3574,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3672,6 +3595,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3692,6 +3616,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3712,6 +3637,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3732,6 +3658,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3745,6 +3672,12 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@patternfly/patternfly": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-6.0.0.tgz", + "integrity": "sha512-Mn92Tt/4okSj1COGCJrgUgh390OOaFCWf0tL0WmigDNUecSHNn1D6Vhpd1hxHQBXvre9eWorzxV2b9yhSEl79Q==", + "license": "MIT" + }, "node_modules/@patternfly/react-core": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-6.0.0.tgz", @@ -3833,6 +3766,65 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", + "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.28", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", @@ -3918,6 +3910,232 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@swc/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz", + "integrity": "sha512-rQ4dS6GAdmtzKiCRt3LFVxl37FaY1cgL9kSUTnhQ2xc3fmHOd7jdJK/V4pSZMG1ruGTd0bsi34O2R0Olg9Zo/w==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.17" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.10.1", + "@swc/core-darwin-x64": "1.10.1", + "@swc/core-linux-arm-gnueabihf": "1.10.1", + "@swc/core-linux-arm64-gnu": "1.10.1", + "@swc/core-linux-arm64-musl": "1.10.1", + "@swc/core-linux-x64-gnu": "1.10.1", + "@swc/core-linux-x64-musl": "1.10.1", + "@swc/core-win32-arm64-msvc": "1.10.1", + "@swc/core-win32-ia32-msvc": "1.10.1", + "@swc/core-win32-x64-msvc": "1.10.1" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.1.tgz", + "integrity": "sha512-NyELPp8EsVZtxH/mEqvzSyWpfPJ1lugpTQcSlMduZLj1EASLO4sC8wt8hmL1aizRlsbjCX+r0PyL+l0xQ64/6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.1.tgz", + "integrity": "sha512-L4BNt1fdQ5ZZhAk5qoDfUnXRabDOXKnXBxMDJ+PWLSxOGBbWE6aJTnu4zbGjJvtot0KM46m2LPAPY8ttknqaZA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.1.tgz", + "integrity": "sha512-Y1u9OqCHgvVp2tYQAJ7hcU9qO5brDMIrA5R31rwWQIAKDkJKtv3IlTHF0hrbWk1wPR0ZdngkQSJZple7G+Grvw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.1.tgz", + "integrity": "sha512-tNQHO/UKdtnqjc7o04iRXng1wTUXPgVd8Y6LI4qIbHVoVPwksZydISjMcilKNLKIwOoUQAkxyJ16SlOAeADzhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.1.tgz", + "integrity": "sha512-x0L2Pd9weQ6n8dI1z1Isq00VHFvpBClwQJvrt3NHzmR+1wCT/gcYl1tp9P5xHh3ldM8Cn4UjWCw+7PaUgg8FcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.1.tgz", + "integrity": "sha512-yyYEwQcObV3AUsC79rSzN9z6kiWxKAVJ6Ntwq2N9YoZqSPYph+4/Am5fM1xEQYf/kb99csj0FgOelomJSobxQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.1.tgz", + "integrity": "sha512-tcaS43Ydd7Fk7sW5ROpaf2Kq1zR+sI5K0RM+0qYLYYurvsJruj3GhBCaiN3gkzd8m/8wkqNqtVklWaQYSDsyqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.1.tgz", + "integrity": "sha512-D3Qo1voA7AkbOzQ2UGuKNHfYGKL6eejN8VWOoQYtGHHQi1p5KK/Q7V1ku55oxXBsj79Ny5FRMqiRJpVGad7bjQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.1.tgz", + "integrity": "sha512-WalYdFoU3454Og+sDKHM1MrjvxUGwA2oralknXkXL8S0I/8RkWZOB++p3pLaGbTvOO++T+6znFbQdR8KRaa7DA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.1.tgz", + "integrity": "sha512-JWobfQDbTnoqaIwPKQ3DVSywihVXlQMbDuwik/dDWlj33A8oEHcjPOGs4OqcA3RHv24i+lfCQpM3Mn4FAMfacA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", + "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@testing-library/cypress": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-10.0.2.tgz", @@ -4179,9 +4397,9 @@ "license": "MIT" }, "node_modules/@types/dompurify": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", - "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.4.0.tgz", + "integrity": "sha512-IDBwO5IZhrKvHFUl+clZxgf3hn2b/lU6H1KaBShPkQyGJUQ0xwebezIPSuiyGwfz1UzJWQl4M7BDxtHtCCPlTg==", "dev": true, "license": "MIT", "dependencies": { @@ -5287,6 +5505,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -7159,6 +7390,18 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-js-pure": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", + "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -8047,6 +8290,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "license": "Apache-2.0", "optional": true, "bin": { @@ -8229,9 +8473,10 @@ } }, "node_modules/dompurify": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.0.tgz", - "integrity": "sha512-AMdOzK44oFWqHEi0wpOqix/fUNY707OmoeFDnbi3Q5I8uOpy21ufUA5cDJPr0bosxrflOVD/H2DMSvuGKJGfmQ==" + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.8.tgz", + "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==", + "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/domutils": { "version": "2.8.0", @@ -8289,16 +8534,13 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=10" } }, "node_modules/dotenv-defaults": { @@ -8311,30 +8553,24 @@ "dotenv": "^8.2.0" } }, - "node_modules/dotenv-defaults/node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10" - } + "license": "BSD-2-Clause" }, "node_modules/dotenv-webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", - "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-6.0.4.tgz", + "integrity": "sha512-WiTPNLanDNJ1O8AvgkBpsbarw78a4PMYG2EfJcQoxTHFWy+ji213HR+3f4PhWB1RBumiD9cbiuC3SNxJXbBp9g==", "dev": true, "license": "MIT", "dependencies": { - "dotenv-defaults": "^2.0.2" - }, - "engines": { - "node": ">=10" + "dotenv-defaults": "^2.0.1" }, "peerDependencies": { - "webpack": "^4 || ^5" + "webpack": "^1 || ^2 || ^3 || ^4 || ^5" } }, "node_modules/duplexer": { @@ -8518,6 +8754,16 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -10126,6 +10372,146 @@ "node": "*" } }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/form-data": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", @@ -10198,6 +10584,13 @@ "node": ">=10" } }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true, + "license": "Unlicense" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -11175,6 +11568,7 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -12188,22 +12582,6 @@ "node": ">= 0.4" } }, - "node_modules/jackspeak": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", - "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -14133,16 +14511,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mocha": { "version": "10.8.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", @@ -14597,10 +14965,18 @@ "tslib": "^2.0.3" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, "license": "MIT", "optional": true }, @@ -15548,13 +15924,6 @@ "node": ">=8" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -15673,33 +16042,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", - "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/path-to-regexp": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", @@ -16912,6 +17254,16 @@ "dev": true, "license": "MIT" }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-router": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.0.2.tgz", @@ -17412,96 +17764,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -17616,6 +17878,7 @@ "version": "1.80.6", "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.6.tgz", "integrity": "sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==", + "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -17633,30 +17896,30 @@ } }, "node_modules/sass-loader": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", - "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", + "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", "dev": true, "license": "MIT", "dependencies": { "neo-async": "^2.6.2" }, "engines": { - "node": ">= 18.12.0" + "node": ">= 14.15.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", + "fibers": ">= 3.1.0", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "@rspack/core": { + "fibers": { "optional": true }, "node-sass": { @@ -17667,9 +17930,6 @@ }, "sass-embedded": { "optional": true - }, - "webpack": { - "optional": true } } }, @@ -17677,6 +17937,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -17692,6 +17953,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 14.16.0" @@ -18330,6 +18592,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -18471,6 +18734,22 @@ "wbuf": "^1.7.3" } }, + "node_modules/speed-measure-webpack-plugin": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.5.0.tgz", + "integrity": "sha512-Re0wX5CtM6gW7bZA64ONOfEPEhwbiSF/vz6e2GvadjuaPrQcHTQdRGsD8+BE7iUOysXH8tIenkPCQBEcspXsNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": "^1 || ^2 || ^3 || ^4 || ^5" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -18527,6 +18806,13 @@ "node": ">=8" } }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -18576,29 +18862,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -18739,20 +19002,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -18818,20 +19067,43 @@ } }, "node_modules/style-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", - "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", "dev": true, "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, "engines": { - "node": ">= 18.12.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.27.0" + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/style-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/stylehacks": { @@ -18900,19 +19172,57 @@ } }, "node_modules/svg-url-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-8.0.0.tgz", - "integrity": "sha512-5doSXvl18hY1fGsRLdhWAU5jgzgxJ06/gc/26cpuDnN0xOz1HmmfhkpL29SSrdIvhtxQ1UwGzmk7wTT/l48mKw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-6.0.0.tgz", + "integrity": "sha512-Qr5SCKxyxKcRnvnVrO3iQj9EX/v40UiGEMshgegzV7vpo3yc+HexELOdtWcA3MKjL8IyZZ1zOdcILmDEa/8JJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "file-loader": "~6.0.0", + "loader-utils": "~2.0.0" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/svg-url-loader/node_modules/file-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz", + "integrity": "sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ==", "dev": true, "license": "MIT", "dependencies": { - "file-loader": "~6.2.0" + "loader-utils": "^2.0.0", + "schema-utils": "^2.6.5" }, "engines": { - "node": ">=14" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/svg-url-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/svgo": { @@ -19014,6 +19324,20 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -20838,25 +21162,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/clients/ui/frontend/package.json b/clients/ui/frontend/package.json index 510d3970..7e86bbd5 100644 --- a/clients/ui/frontend/package.json +++ b/clients/ui/frontend/package.json @@ -14,8 +14,8 @@ "build:analyze": "run-s build build:bundle-profile build:bundle-analyze", "build:bundle-profile": "webpack --config ./config/webpack.prod.js --profile --json > ./bundle.stats.json", "build:bundle-analyze": "webpack-bundle-analyzer ./bundle.stats.json", - "build:clean": "rimraf ./public", "build:prod": "webpack --config ./config/webpack.prod.js", + "build:clean": "rm -rf ./dist", "start:dev": "webpack serve --hot --color --config ./config/webpack.dev.js", "test": "run-s test:lint test:unit test:cypress-ci", "test:cypress-ci": "npx concurrently -P -k -s first \"npm run cypress:server:build && npm run cypress:server\" \"npx wait-on tcp:127.0.0.1:9001 && npm run cypress:run:mock -- {@}\" -- ", @@ -27,10 +27,12 @@ "cypress:open:mock": "CY_MOCK=1 npm run cypress:open -- ", "cypress:run": "cypress run -b chrome --project src/__tests__/cypress", "cypress:run:mock": "CY_MOCK=1 npm run cypress:run -- ", - "cypress:server:build": "POLL_INTERVAL=9999999 FAST_POLL_INTERVAL=9999999 npm run build", - "cypress:server": "serve ./dist -p 9001 -s -L" + "cypress:server:build": "DIST_DIR=./public-cypress POLL_INTERVAL=9999999 FAST_POLL_INTERVAL=9999999 npm run build", + "cypress:server": "serve ./public-cypress -p 9001 -s -L" }, "devDependencies": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", + "@swc/core": "^1.9.1", "@babel/preset-env": "^7.21.5", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.5", @@ -44,7 +46,7 @@ "@testing-library/react": "^16.0.0", "@testing-library/user-event": "14.5.2", "@types/classnames": "^2.3.1", - "@types/dompurify": "^3.0.5", + "@types/dompurify": "^2.2.6", "@types/jest": "^29.5.13", "@types/lodash-es": "^4.17.8", "@types/react-dom": "^18.3.1", @@ -60,9 +62,12 @@ "cypress-high-resolution": "^1.0.0", "cypress-mochawesome-reporter": "^3.8.2", "cypress-multi-reporters": "^2.0.4", - "dotenv": "^16.4.5", - "dotenv-webpack": "^8.1.0", + "dotenv": "^8.2.0", + "dotenv-expand": "^5.1.0", + "dotenv-webpack": "^6.0.0", "expect": "^29.7.0", + "file-loader": "^6.1.1", + "fork-ts-checker-webpack-plugin": "^9.0.2", "html-webpack-plugin": "^5.6.3", "imagemin": "^9.0.0", "jest": "^29.7.0", @@ -73,13 +78,16 @@ "prettier": "^3.3.3", "prop-types": "^15.8.1", "raw-loader": "^4.0.2", + "react-refresh": "^0.14.2", "react-router-dom": "^7.0.2", "regenerator-runtime": "^0.14.1", - "rimraf": "^6.0.1", - "sass-loader": "^16.0.1", + "sass": "^1.56.2", + "sass-loader": "^13.2.0", "serve": "^14.2.4", - "style-loader": "^4.0.0", - "svg-url-loader": "^8.0.0", + "speed-measure-webpack-plugin": "^1.5.0", + "style-loader": "^2.0.0", + "svg-url-loader": "^6.0.0", + "swc-loader": "^0.2.6", "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.2.5", "ts-loader": "^9.5.1", @@ -87,7 +95,7 @@ "tslib": "^2.7.0", "typescript": "^5.7.2", "url-loader": "^4.1.1", - "webpack": "^5.95.0", + "webpack": "^5.96.1", "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.1.0", @@ -96,6 +104,7 @@ "dependencies": { "@emotion/react": "^11.13.5", "@emotion/styled": "^11.13.5", + "@patternfly/patternfly": "^6.0.0", "@patternfly/react-core": "6.0.0", "@patternfly/react-icons": "6.0.0", "@patternfly/react-styles": "6.0.0", @@ -107,7 +116,7 @@ "react-dom": "^18", "react-router": "^7.0.2", "sass": "^1.78.0", - "dompurify": "^3.2.0", + "dompurify": "^2.2.6", "showdown": "^2.1.0", "classnames": "^2.2.6" }, diff --git a/clients/ui/frontend/src/__tests__/unit/testUtils/hooks.spec.ts b/clients/ui/frontend/src/__tests__/unit/testUtils/hooks.spec.ts index f570f974..d2509314 100644 --- a/clients/ui/frontend/src/__tests__/unit/testUtils/hooks.spec.ts +++ b/clients/ui/frontend/src/__tests__/unit/testUtils/hooks.spec.ts @@ -70,11 +70,11 @@ describe('hook test utils', () => { expect(renderResult).hookToBe('Hello world!'); expect(renderResult).hookToStrictEqual('Hello world!'); - renderResult.rerender({ who: 'world', showCount: true }); + renderResult.rerender({ who: 'world' }); expect(renderResult).hookToHaveUpdateCount(3); - expect(renderResult).hookToBe('Hello world! x3'); - expect(renderResult).hookToStrictEqual('Hello world! x3'); + expect(renderResult).hookToBe('Hello world!'); + expect(renderResult).hookToStrictEqual('Hello world!'); }); it('should use waitForNextUpdate for async update testing', async () => { diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetails.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetails.tsx index 8bbcd176..c59fecab 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetails.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetails.tsx @@ -90,7 +90,7 @@ const ModelVersionsDetails: React.FC = ({ tab, ...page /> - + ) diff --git a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx index eb67141c..8a106325 100644 --- a/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx +++ b/clients/ui/frontend/src/app/pages/modelRegistry/screens/RegisterModel/RegistrationCommonFormSections.tsx @@ -217,7 +217,7 @@ const RegistrationCommonFormSections: React.FC diff --git a/clients/ui/frontend/src/images/logo-dark-theme.svg b/clients/ui/frontend/src/images/logo-dark-theme.svg new file mode 100644 index 00000000..fb06122e --- /dev/null +++ b/clients/ui/frontend/src/images/logo-dark-theme.svg @@ -0,0 +1,43 @@ + + + + Kubeflow Logo + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clients/ui/frontend/src/images/logo.svg b/clients/ui/frontend/src/images/logo-light-theme.svg similarity index 100% rename from clients/ui/frontend/src/images/logo.svg rename to clients/ui/frontend/src/images/logo-light-theme.svg diff --git a/clients/ui/frontend/src/shared/components/design/utils.ts b/clients/ui/frontend/src/shared/components/design/utils.ts index df39b392..36d39055 100644 --- a/clients/ui/frontend/src/shared/components/design/utils.ts +++ b/clients/ui/frontend/src/shared/components/design/utils.ts @@ -7,6 +7,14 @@ import './vars.scss'; /* eslint-disable @typescript-eslint/no-unnecessary-condition */ // These conditions are required for future object types that may be added later. +export enum SectionType { + setup = 'set-up', + organize = 'organize', + training = 'training', + serving = 'serving', + general = 'general', +} + export enum ProjectObjectType { registeredModels = 'registered-models', } @@ -44,3 +52,37 @@ export const typedEmptyImage = (objectType: ProjectObjectType, option?: string): return ''; } }; + +export const sectionTypeBackgroundColor = (sectionType: SectionType): string => { + switch (sectionType) { + case SectionType.setup: + return 'var(--ai-set-up--BackgroundColor)'; + case SectionType.organize: + return 'var(--ai-organize--BackgroundColor)'; + case SectionType.training: + return 'var(--ai-training--BackgroundColor)'; + case SectionType.serving: + return 'var(--ai-serving--BackgroundColor)'; + case SectionType.general: + return 'var(--ai-general--BackgroundColor)'; + default: + return ''; + } +}; + +export const sectionTypeBorderColor = (sectionType: SectionType): string => { + switch (sectionType) { + case SectionType.setup: + return 'var(--ai-set-up--BorderColor)'; + case SectionType.organize: + return 'var(--ai-organize--BorderColor)'; + case SectionType.training: + return 'var(--ai-training--BorderColor)'; + case SectionType.serving: + return 'var(--ai-serving--BorderColor)'; + case SectionType.general: + return 'var(--ai-general--BorderColor)'; + default: + return ''; + } +}; diff --git a/clients/ui/frontend/tsconfig.json b/clients/ui/frontend/tsconfig.json index 674889be..1d11ee22 100644 --- a/clients/ui/frontend/tsconfig.json +++ b/clients/ui/frontend/tsconfig.json @@ -1,14 +1,13 @@ { "compilerOptions": { - "baseUrl": "./src", "rootDir": ".", "outDir": "dist", "module": "esnext", "target": "es5", "lib": [ - "ESNext.Array", "es6", - "dom" + "dom", + "ES2023.Array" ], "sourceMap": true, "jsx": "react", @@ -22,21 +21,26 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, + "baseUrl": "./src", "paths": { - "~/*": ["./*"] + "~/*": [ + "./*" + ] }, "importHelpers": true, - "skipLibCheck": true + "skipLibCheck": true, + "noErrorTruncation": true }, "include": [ "**/*.ts", "**/*.tsx", "**/*.jsx", - "**/*.js", + "**/*.js" ], "exclude": [ "node_modules", "dist", + "public-cypress", "src/__tests__/cypress" ] -} +} \ No newline at end of file