diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 40e856d4eaa6..a055c1f19079 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -7,9 +7,13 @@ //= require lookup_keys $(function() { + if(window.allJsLoaded){ + $(document).trigger('ContentLoad'); + } + else { $(document).on('loadJS', function() { $(document).trigger('ContentLoad'); - }); + });} }); @@ -30,7 +34,6 @@ var handleDisabledClick = function(event, element){ $(document).on('click', 'a[disabled="disabled"]', function(event) { return handleDisabledClick(event, this); }); - function onContentLoad() { if ($('input[focus_on_load=true]').length > 0) { $('input[focus_on_load]') diff --git a/app/assets/javascripts/late_load.js b/app/assets/javascripts/late_load.js index 71189283253a..55a0a4f3d540 100644 --- a/app/assets/javascripts/late_load.js +++ b/app/assets/javascripts/late_load.js @@ -2,11 +2,13 @@ function load_dynamic_javascripts(html) { function waitForAllLoaded() { // Wait for all plugins js modules to be loaded before loading the javascript content return new Promise(function(resolve) { - if (Object.values(window.allPluginsLoaded).every(Boolean)) { + // window.allPluginsLoaded is set to {} when plugins are starting to load + // if there are no plugins window.allPluginsLoaded is never defined + if (window.allPluginsLoaded === undefined || Object.values(window.allPluginsLoaded).every(Boolean)) { resolve(); } else { function handleLoad() { - if (Object.values(window.allPluginsLoaded).every(Boolean)) { + if (window.allPluginsLoaded === undefined || Object.values(window.allPluginsLoaded).every(Boolean)) { resolve(); // Remove the event listener document.removeEventListener('loadPlugin', handleLoad); diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index 7ed1a1dd81f3..83e0ca561ea4 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -107,9 +107,8 @@ def javascript_include_tag(*params, **kwargs) end end - + # @deprecated Previously provided by webpack-rails def webpack_asset_paths(plugin_name, extension: 'js') - # @deprecated Previously provided by webpack-rails if extension == 'js' Foreman::Deprecation.deprecation_warning('3.12', '`webpack_asset_paths` is deprecated, use `content_for(:javascripts) { webpacked_plugins_js_for(plugin_name) }` instead.') [{ diff --git a/app/helpers/reactjs_helper.rb b/app/helpers/reactjs_helper.rb index 42399beadd7c..af2bedbcdccb 100644 --- a/app/helpers/reactjs_helper.rb +++ b/app/helpers/reactjs_helper.rb @@ -21,19 +21,19 @@ def webpacked_plugins_with_global_js end def webpacked_plugins_css_for(*plugin_names) - Foreman::Deprecation.deprecation_warning('3.9', '`webpacked_plugins_css_for` is deprecated, plugin css is already loaded.') + Foreman::Deprecation.deprecation_warning('3.12', '`webpacked_plugins_css_for` is deprecated, plugin css is already loaded.') end def read_webpack_manifest - root = File.expand_path(File.dirname(__FILE__) + "/../..") - file = File.read(root + '/public/webpack/manifest.json') - JSON.parse(file) + JSON.parse(Rails.root.join('public/webpack/manifest.json').read) end def get_webpack_foreman_vendor_js - data = read_webpack_manifest - foreman_vendor_js = data['assetsByChunkName']['foreman-vendor'].find { |value| value.end_with?('.js') } - javascript_include_tag("/webpack/#{foreman_vendor_js}") + Rails.cache.fetch('webpack_foreman_vendor_js', expires_in: 1.minute) do + data = read_webpack_manifest + foreman_vendor_js = data['assetsByChunkName']['foreman-vendor'].find { |value| value.end_with?('.js') } + javascript_include_tag("/webpack/#{foreman_vendor_js}") + end end def get_webpack_foreman_vendor_css @@ -54,20 +54,22 @@ def select_requested_plugins(plugin_names) def js_tags_for(requested_plugins) requested_plugins.map do |plugin| - javascript_tag("window.tfm.tools.loadPluginModule('/webpack/#{plugin.to_s.tr('-', '_')}','#{plugin.to_s.tr('-', '_')}','./index');".html_safe) + name = plugin.to_s.tr('-', '_') + javascript_tag("window.tfm.tools.loadPluginModule('/webpack/#{name}','#{name}','./index');".html_safe) end end def global_js_tags(requested_plugins) requested_plugins.map do |plugin| plugin[:files].map do |file| - javascript_tag("window.tfm.tools.loadPluginModule('/webpack/#{plugin[:id].to_s.tr('-', '_')}','#{plugin[:id].to_s.tr('-', '_')}','./#{file}_index');".html_safe) + name = plugin[:id].to_s.tr('-', '_') + javascript_tag("window.tfm.tools.loadPluginModule('/webpack/#{name}','#{name}','./#{file}_index');".html_safe) end end end def css_tags_for(requested_plugins) - Foreman::Deprecation.deprecation_warning('3.12', '`css_tags_for` is deprecated, No need to load CSS separately, since it should be referneced from the corresponding JS file.') + Foreman::Deprecation.deprecation_warning('3.12', '`css_tags_for` is deprecated, No need to load CSS separately, since it should be referenced from the corresponding JS file.') [] end diff --git a/app/services/foreman/env_settings_loader.rb b/app/services/foreman/env_settings_loader.rb index 19d55419d836..12701c88a5e3 100644 --- a/app/services/foreman/env_settings_loader.rb +++ b/app/services/foreman/env_settings_loader.rb @@ -31,8 +31,6 @@ def settings_map 'FOREMAN_REQUIRE_SSL' => [:boolean, :require_ssl], 'FOREMAN_SUPPORT_JSONP' => [:boolean, :support_jsonp], 'FOREMAN_MARK_TRANSLATED' => [:boolean, :mark_translated], - 'FOREMAN_WEBPACK_DEV_SERVER' => [:boolean, :webpack_dev_server], - 'FOREMAN_WEBPACK_DEV_SERVER_HTTPS' => [:boolean, :webpack_dev_server_https], 'FOREMAN_ASSETS_DEBUG' => [:boolean, :assets_debug], 'FOREMAN_HSTS_ENABLED' => [:boolean, :hsts_enabled], 'FOREMAN_DOMAIN' => [:string, :domain], diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 01cc2ac5e442..d81d28a330b2 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -30,7 +30,6 @@ <%= javascript_include_tag "locale/#{FastGettext.locale}/app" %> <%= locale_js_tags %> - <%= stylesheet_link_tag('/webpack/bundle', :extension => 'css') %> <%= yield(:head) %> diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 2901d243a364..2e5f32b42293 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,13 +1,3 @@ -module Webpack - module Rails - class Manifest - class << self - attr_writer :manifest - end - end - end -end - # Be sure to restart your server when you modify this file. Foreman::Application.configure do |app| # Version of your assets, change this if you want to expire all your assets. diff --git a/config/settings.yaml.example b/config/settings.yaml.example index 38d71745baab..26059817e3cd 100644 --- a/config/settings.yaml.example +++ b/config/settings.yaml.example @@ -11,15 +11,6 @@ # Mark translated strings with X characters (for developers) :mark_translated: false -# Use the webpack development server? set to false to disable (for developers) -# Make sure to run `rake webpack:compile` if disabled. -:webpack_dev_server: true - -# If you run Foreman in development behind some proxy or use HTTPS you need -# to enable HTTPS for webpack dev server too, otherwise you'd get mixed content -# errors in your browser -:webpack_dev_server_https: false - # Assets in development are not bundled/minified # Do not set this to false if you plan to edit assets (css, js, etc.) :assets_debug: false diff --git a/config/webpack.config.js b/config/webpack.config.js index 63e5de8da056..bdd4f14e9c89 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -8,16 +8,14 @@ dotenv.config(); var ForemanVendorPlugin = require('@theforeman/vendor') .WebpackForemanVendorPlugin; var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin; -var MiniCssExtractPlugin = require('mini-css-extract-plugin'); var vendorEntry = require('./webpack.vendor'); var fs = require('fs'); const { ModuleFederationPlugin } = require('webpack').container; var pluginUtils = require('../script/plugin_webpack_directories'); -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') - .BundleAnalyzerPlugin; -const { getForemanFilePaths } = require('../script/get_webpack_shared_files'); class AddRuntimeRequirement { + // to avoid "webpackRequire.l is not a function" error + // enables use of webpack require inside promise new promise apply(compiler) { compiler.hooks.compilation.tap('AddRuntimeRequirement', compilation => { const { RuntimeGlobals } = compiler.webpack; @@ -52,12 +50,7 @@ const supportedLanguagesRE = new RegExp( `/(${supportedLanguages().join('|')})$` ); -var bundleEntry = path.join( - __dirname, - '..', - 'webpack/assets/javascripts/bundle.js' -); -const commonConfig = function(env, argv) { +const commonConfig = function() { var production = process.env.RAILS_ENV === 'production' || process.env.NODE_ENV === 'production'; @@ -70,15 +63,14 @@ const commonConfig = function(env, argv) { splitChunks: false, }; } else { + config.devtool = 'inline-source-map'; config.optimization = { splitChunks: false, }; - config.devtool = 'inline-source-map'; } return { ...config, mode, - resolve: { fallback: { path: require.resolve('path-browserify'), @@ -153,39 +145,19 @@ const commonConfig = function(env, argv) { supportedLanguagesRE ), new AddRuntimeRequirement(), - // new webpack.optimize.ModuleConcatenationPlugin(), ], - infrastructureLogging: { - colors: true, - level: 'verbose', - }, - stats: { - logging: 'verbose', - preset: 'verbose', - }, - }; -}; - -const moduleFederationSharedConfig = function(env, argv) { - return { - react: { singleton: true }, - 'react-dom': { singleton: true }, - '@theforeman/vendor': { singleton: true }, - '@theforeman/vendor-dev': { singleton: true }, - '@theforeman/vendor-scss': { singleton: true }, - '@theforeman/vendor-scss-variables': { singleton: true }, - '@babel/core': { singleton: true }, - webpack: { singleton: true }, - 'bundle.js': { singleton: true }, - 'path-browserify': { singleton: true }, - 'os-browserify': { singleton: true }, + stats: process.env.WEBPACK_STATS || 'normal', }; }; -const coreConfig = function(env, argv) { - var config = commonConfig(env, argv); - +const coreConfig = function() { + var config = commonConfig(); var manifestFilename = 'manifest.json'; + var bundleEntry = path.join( + __dirname, + '..', + 'webpack/assets/javascripts/bundle.js' + ); config.context = path.resolve(__dirname, '..'); config.entry = { bundle: { import: bundleEntry, dependOn: 'vendor' }, @@ -197,97 +169,49 @@ const coreConfig = function(env, argv) { }; var plugins = config.plugins; - const webpackDirectory = path.resolve( - __dirname, - '..', - 'webpack', - 'assets', - 'javascripts', - 'react_app' - ); - const coreShared = {}; - - getForemanFilePaths(false).forEach(file => { - const key = file.replace(webpackDirectory, '').replace(/\.(js|jsx)$/, ''); - coreShared['./' + file] = { + // since CardTemplate uses CardExpansionContext between plugins, we need to make sure there is only one source of it, otherwise multiple contexts will be created and only one will be initialized correctly + const coreShared = { + './webpack/assets/javascripts/react_app/components/HostDetails/Templates/CardItem/CardTemplate/index.js': { singleton: true, eager: true, - shareKey: key, - }; - }); + shareKey: + 'foreman/webpack/assets/javascripts/react_app/components/HostDetails/Templates/CardItem/CardTemplate/index.js', + }, + }; + plugins.push( new ModuleFederationPlugin({ name: 'foremanReact', shared: { - ...moduleFederationSharedConfig(env, argv), - ...coreShared, }, }) ); - plugins.push( - new MiniCssExtractPlugin({ - ignoreOrder: true, - filename: '[name].css', - chunkFilename: '[id].css', - }) - ); plugins.push( new StatsWriterPlugin({ filename: manifestFilename, - fields: null, - transform: function(data, opts) { - return JSON.stringify( - { - assetsByChunkName: data.assetsByChunkName, - errors: data.errors, - warnings: data.warnings, - }, - null, - 2 - ); - }, - }) - ); - - plugins.push( - new BundleAnalyzerPlugin({ - generateStatsFile: true, - analyzerMode: 'static', - openAnalyzer: false, - statsFilename: 'stats.json', }) ); config.plugins = plugins; var rules = config.module.rules; rules.push({ test: /\.(sa|sc|c)ss$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - options: { - publicPath: path.join(__dirname, '..', 'public', 'webpack'), - }, - }, - 'css-loader', - 'sass-loader', - ], + use: ['style-loader', 'css-loader', 'sass-loader'], }); config.module.rules = rules; return config; }; -const pluginConfig = function(env, argv) { - var pluginEnv = env.plugin; - const pluginRoot = pluginEnv.root; - const pluginName = pluginEnv.name.replace('-', '_'); // module federation doesnt like - - var config = commonConfig(env, argv); +const pluginConfig = function(plugin) { + const pluginRoot = plugin.root; + const pluginName = plugin.name.replace('-', '_'); // module federation doesnt like - + var config = commonConfig(); config.context = path.join(pluginRoot, 'webpack'); config.entry = {}; var pluginEntries = { './index': path.resolve(pluginRoot, 'webpack', 'index'), }; - pluginEnv.entries.filter(Boolean).forEach(entry => { + plugin.entries.filter(Boolean).forEach(entry => { pluginEntries[`./${entry}_index`] = path.resolve( pluginRoot, 'webpack', @@ -300,7 +224,6 @@ const pluginConfig = function(env, argv) { publicPath: '/webpack/' + pluginName + '/', uniqueName: pluginName, }; - var configModules = config.resolve.modules || []; // make webpack to resolve modules from core first configModules.unshift(path.resolve(__dirname, '..', 'node_modules')); @@ -311,92 +234,36 @@ const pluginConfig = function(env, argv) { //get the list of webpack plugins var plugins = config.plugins; - const webpackDirectory = path.resolve( + const pathToCardTemplate = path.resolve( __dirname, '..', - 'webpack', - 'assets', - 'javascripts', - 'react_app' + 'webpack/assets/javascripts/react_app/components/HostDetails/Templates/CardItem/CardTemplate/index.js' ); - - const pluginShared = {}; - getForemanFilePaths(true).forEach(file => { - const key = file - .replace(webpackDirectory, '') - .replace(/\.(js|jsx)$/, '') - .replace('../../foreman/', ''); - pluginShared[file] = { + const relativePath = path.relative(pluginRoot, pathToCardTemplate); + const pluginShared = { + ['../' + relativePath]: { singleton: true, - shareKey: key, - }; - }); - - const keys = [...Object.keys(pluginShared)]; - const newObj = {}; - keys.forEach(key => { - newObj[key] = pluginShared[key]; - }); + shareKey: + 'foreman/webpack/assets/javascripts/react_app/components/HostDetails/Templates/CardItem/CardTemplate/index.js', + }, + }; plugins.push( new ModuleFederationPlugin({ name: pluginName, filename: pluginName + '_remoteEntry.js', shared: { - ...moduleFederationSharedConfig(env, argv), ...pluginShared, }, exposes: pluginEntries, }) ); - plugins.push( - new MiniCssExtractPlugin({ - ignoreOrder: true, - filename: pluginName + '/[name].css', - chunkFilename: pluginName + '/[id].css', - }) - ); - const manifestFilename = pluginName + '_manifest.json'; - plugins.push( - new StatsWriterPlugin({ - filename: manifestFilename, - fields: null, - transform: function(data, opts) { - return JSON.stringify( - { - assetsByChunkName: data.assetsByChunkName, - errors: data.errors, - warnings: data.warnings, - }, - null, - 2 - ); - }, - }) - ); - plugins.push( - new BundleAnalyzerPlugin({ - generateStatsFile: true, - analyzerMode: 'static', - openAnalyzer: false, - statsFilename: pluginName + '_stats.json', - }) - ); config.plugins = plugins; var rules = config.module.rules; rules.push({ test: /\.(sa|sc|c)ss$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - }, - 'css-loader', - 'sass-loader', - ], + use: ['style-loader', 'css-loader', 'sass-loader'], }); config.module.rules = rules; - config.optimization = { - ...config.optimization, - }; return config; }; @@ -428,8 +295,6 @@ module.exports = function(env, argv) { })); pluginsConfigEnv.push({ plugin: { - // routes: pluginDirKeys.includes(pluginDirKey + ':routes'), - // global: pluginDirKeys.includes(pluginDirKey + ':global'), ...pluginExtras, name: pluginDirKey, root: pluginsDirs.plugins[pluginDirKey].root, @@ -437,19 +302,10 @@ module.exports = function(env, argv) { }); } }); - - console.log('CHECK CSS') - if (fs.existsSync('node_modules/@theforeman/vendor/scss/variables.scss')) { - console.log('The file node_modules/@theforeman/vendor/scss/variables.scss exists.'); - } else { - console.log('The file node_modules/@theforeman/vendor/scss/variables.scss does not exist.'); - } let configs = []; const pluginsInfoValues = Object.values(pluginsInfo); if (pluginsInfoValues.length > 0) { - configs = pluginsInfoValues.map(plugin => - pluginConfig({ ...env, plugin }, argv) - ); + configs = pluginsInfoValues.map(plugin => pluginConfig(plugin)); } return [coreConfig(env, argv), ...configs]; }; diff --git a/developer_docs/getting-started.asciidoc b/developer_docs/getting-started.asciidoc index 975767535ff6..f1e1e68cd773 100644 --- a/developer_docs/getting-started.asciidoc +++ b/developer_docs/getting-started.asciidoc @@ -8,28 +8,12 @@ Following steps are required to setup a webpack development environment: -1. **Settings** - There are 2 relevant settings in `config/settings.yml`. At least `webpack_dev_server` should be set to true: -+ -[source,yaml] ----- -# Use the webpack development server? -# Should be set to true if you want to conveniently develop webpack-processed code. -# Make sure to run `rake webpack:compile` if disabled. -:webpack_dev_server: true - -# If you run Foreman in development behind some proxy or use HTTPS you need -# to enable HTTPS for webpack dev server too, otherwise you'd get mixed content -# errors in your browser -:webpack_dev_server_https: true ----- -+ -2. **Dependencies** +1. **Dependencies** Make sure you have all npm dependencies up to date: `npm install` Alternatively you can run the install command with option `--no-optional` which skips packages that aren't required and can save you some space. -3. **Running webpack** +2. **Running webpack** There are several ways of executing webpack: - using [foreman runner](https://github.com/ddollar/foreman): `foreman start` (starts both rails and webpack server) @@ -40,7 +24,7 @@ Following steps are required to setup a webpack development environment: --config config/webpack.config.js ``` -4. **Additional config** +3. **Additional config** Both `foreman start` and `foreman-start-dev` support `WEBPACK_OPTS` environment variable for passing additional options. This is handy for example when you have development setup with Katello and want to use correct certificates. An example of such setup: + diff --git a/lib/tasks/jenkins.rake b/lib/tasks/jenkins.rake index 34ad6f62c3fa..d120bb1568cc 100644 --- a/lib/tasks/jenkins.rake +++ b/lib/tasks/jenkins.rake @@ -3,7 +3,7 @@ begin namespace :jenkins do task :unit => ['jenkins:setup:minitest', 'rake:test:units', 'rake:test:functionals', 'rake:test:graphql'] - task :integration => ['webpack:compile', 'jenkins:setup:minitest', 'rake:test:integration'] + task :integration => ['webpack:compile', 'assets:precompile', 'jenkins:setup:minitest', 'rake:test:integration'] task :functionals => ["jenkins:setup:minitest", 'rake:test:functionals'] task :external => ['rake:test:external'] task :units => ["jenkins:setup:minitest", 'rake:test:units'] diff --git a/package-exclude.json b/package-exclude.json index e9530f094658..83a568845778 100644 --- a/package-exclude.json +++ b/package-exclude.json @@ -30,7 +30,6 @@ "redux-mock-store", "surge", "webpack-bundle-analyzer", - "webpack-stats-plugin", "tabbable", "@adobe/css-tools", "sass" diff --git a/package.json b/package.json index d507764227fd..9207ccd8c97d 100644 --- a/package.json +++ b/package.json @@ -41,20 +41,16 @@ "babel-eslint": "^10.0.0", "babel-loader": "^8.0.0", "cross-env": "^5.2.0", - "css-loader": "4.3.0", + "css-loader": "6.8.1", "css-minimizer-webpack-plugin": "^4.2.2", - "cssnano": "^4.1.10", + "cssnano": "^5.0.1", "dotenv": "^5.0.0", "eslint": "^6.7.2", "eslint-plugin-spellcheck": "0.0.17", "graphql": "^15.5.0", "highlight.js": "~9.14.0", - "mini-css-extract-plugin": "2.7.5", - "node-sass": "6.0.0", - "optimize-css-assets-webpack-plugin": "^4.0.0", + "node-sass": "8.0.0", "path-browserify": "^1.0.1", - "postcss-loader": "4.3.0", - "postcss": "^8.4.12", "prettier": "^1.19.1", "pretty-format": "26.6.2", "raw-loader": "^0.5.1", @@ -62,16 +58,16 @@ "react-dnd-test-utils": "^9.4.0", "react-remarkable": "^1.1.3", "redux-mock-store": "^1.2.2", - "sass-loader": "10.2.0", "sass": "~1.60.0", - "style-loader": "1.3.0", - "stylelint-config-standard": "^18.0.0", + "sass-loader": "10.2.0", + "style-loader": "^1.3.0", "stylelint": "^9.3.0", + "stylelint-config-standard": "^18.0.0", "tabbable": "~5.2.0", "url-loader": "4.1.1", + "webpack": "5.75.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "5.0.1", - "webpack-stats-plugin": "^1.0.3", - "webpack": "5.75.0" + "webpack-stats-plugin": "^1.0.3" } } diff --git a/script/get_webpack_shared_files.js b/script/get_webpack_shared_files.js deleted file mode 100644 index 52716b26a645..000000000000 --- a/script/get_webpack_shared_files.js +++ /dev/null @@ -1,77 +0,0 @@ -const path = require('path'); -const fs = require('fs'); - -function getForemanFilePaths(isPlugin) { - // since CardTemplate uses CardExpansionContext between plugins, we need to make sure there is only one source of it, otherwise multiple contexts will be created and only one will be initialized correctly - // This is a function in case we want to add more directories in the future - const paths = [ - path.join( - process.cwd(), - './webpack/assets/javascripts/react_app/components/HostDetails/Templates' - ), - ]; - const acc = []; - paths.forEach(_path => { - acc.push(...getForemanFilePath(isPlugin, _path)); - }); - return acc; -} -function getForemanFilePath(isPlugin, directory) { - const files = fs.readdirSync(directory); - const filePaths = files.reduce((acc, file) => { - const filePath = path.join(directory, file); - const isFile = fs.statSync(filePath).isFile(); - if (isFile) { - if (file.endsWith('.js') && !file.includes('test')) { - if (isPlugin) { - acc.push( - path.join('../../foreman', filePath.replace(process.cwd(), '')) - ); - } else { - acc.push(path.join('./', filePath.replace(process.cwd(), ''))); - } - } - } else { - const subDirectoryFiles = getForemanFilePathsRecursive( - filePath, - isPlugin - ); - acc.push(...subDirectoryFiles); - } - return acc; - }, []); - return filePaths; -} - -function getForemanFilePathsRecursive(directory, isPlugin) { - const files = fs.readdirSync(directory); - - const filePaths = files.reduce((acc, file) => { - const filePath = path.join(directory, file); - const isFile = fs.statSync(filePath).isFile(); - if (isFile) { - if (file.endsWith('.js') && !file.includes('test')) { - if (isPlugin) { - acc.push( - path.join('../../foreman', filePath.replace(process.cwd(), '')) - ); - } else { - acc.push(path.join('./', filePath.replace(process.cwd(), ''))); - } - } - } else { - const subDirectoryFiles = getForemanFilePathsRecursive( - filePath, - isPlugin - ); - acc.push(...subDirectoryFiles); - } - return acc; - }, []); - - return filePaths; -} - -module.exports = { - getForemanFilePaths, -}; diff --git a/test/unit/foreman/env_settings_loader_test.rb b/test/unit/foreman/env_settings_loader_test.rb index 3cd981c2a646..a0d391b85f83 100644 --- a/test/unit/foreman/env_settings_loader_test.rb +++ b/test/unit/foreman/env_settings_loader_test.rb @@ -10,8 +10,6 @@ class EnvSettingsLoaderTest < ActiveSupport::TestCase 'FOREMAN_REQUIRE_SSL' => 'true', 'FOREMAN_SUPPORT_JSONP' => 'false', 'FOREMAN_MARK_TRANSLATED' => 'false', - 'FOREMAN_WEBPACK_DEV_SERVER' => 'false', - 'FOREMAN_WEBPACK_DEV_SERVER_HTTPS' => 'false', 'FOREMAN_ASSETS_DEBUG' => 'false', 'FOREMAN_HSTS_ENABLED' => 'false', 'FOREMAN_DOMAIN' => 'example.com', @@ -43,8 +41,6 @@ class EnvSettingsLoaderTest < ActiveSupport::TestCase require_ssl: true, support_jsonp: false, mark_translated: false, - webpack_dev_server: false, - webpack_dev_server_https: false, assets_debug: false, hsts_enabled: false, domain: 'example.com', diff --git a/webpack/assets/javascripts/react_app/common/AwaitedMount.js b/webpack/assets/javascripts/react_app/common/AwaitedMount.js index 23df91faf43a..00e9f2bf72d7 100644 --- a/webpack/assets/javascripts/react_app/common/AwaitedMount.js +++ b/webpack/assets/javascripts/react_app/common/AwaitedMount.js @@ -8,7 +8,9 @@ import { translate as __ } from './I18n'; export const AwaitedMount = ({ component, data, flattenData }) => { const [mounted, setMounted] = useState(false); const [mountedComponent, setMountedComponent] = useState(null); - const [allPluginsImported, setAllPluginsImported] = useState(false); + const [allPluginsImported, setAllPluginsImported] = useState( + window.allJsLoaded + ); async function mountComponent() { if (componentRegistry.registry[component]) { setMounted(true); @@ -40,7 +42,12 @@ export const AwaitedMount = ({ component, data, flattenData }) => { if (!mounted) mountComponent(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [allPluginsImported]); - return mounted ? mountedComponent :
{__('Loading...')}
; + useEffect(() => { + // Update the component if the data (props) change + if (allPluginsImported) mountComponent(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data]); + return mounted ? mountedComponent : null; }; AwaitedMount.propTypes = { diff --git a/webpack/assets/javascripts/react_app/common/globalIdHelpers.js b/webpack/assets/javascripts/react_app/common/globalIdHelpers.js index 460ab4b9c754..53854715bf42 100644 --- a/webpack/assets/javascripts/react_app/common/globalIdHelpers.js +++ b/webpack/assets/javascripts/react_app/common/globalIdHelpers.js @@ -8,8 +8,6 @@ */ import { Buffer } from 'buffer'; -import { Buffer } from 'buffer'; - const idSeparator = '-'; const versionSeparator = ':'; const defaultVersion = '01'; diff --git a/webpack/assets/javascripts/react_app/common/variables.scss b/webpack/assets/javascripts/react_app/common/variables.scss index dea052e654ae..4f3e5239507d 100644 --- a/webpack/assets/javascripts/react_app/common/variables.scss +++ b/webpack/assets/javascripts/react_app/common/variables.scss @@ -1,3 +1,3 @@ -@import '~@theforeman/vendor/scss/variables'; +@import 'node_modules/@theforeman/vendor/scss/variables.scss'; $header-max-width: calc(#{$pf-global--breakpoint--lg} + 70px); //TODO move into @theforeman/vendor/scss/variables diff --git a/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss b/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss index fee44434dbca..31fdfd1efca8 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/components/ImpersonateIcon/ImpersonateIcon.scss @@ -1,4 +1,4 @@ -@import "~@theforeman/vendor/scss/variables"; +@import "node_modules/@theforeman/vendor/scss/variables"; @keyframes blink { 0% { diff --git a/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss b/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss index 5f7e814d201c..448bcf664ae2 100644 --- a/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss +++ b/webpack/assets/javascripts/react_app/components/Layout/components/TaxonomySwitcher/TaxonomyDropdown.scss @@ -1,4 +1,4 @@ -@import '~@theforeman/vendor/scss/variables'; +@import 'node_modules/@theforeman/vendor/scss/variables'; .pf-c-masthead .pf-c-toolbar { .pf-c-context-selector__menu-search { diff --git a/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss b/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss index 0f15a369da50..c1b7a6d7ab8c 100644 --- a/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss +++ b/webpack/assets/javascripts/react_app/components/LoginPage/LoginPage.scss @@ -1,4 +1,4 @@ -@import '~@theforeman/vendor/scss/variables'; +@import 'node_modules/@theforeman/vendor/scss/variables'; $caption_font_weight: 600; $background_image: url('../LoginPage/background.svg'); diff --git a/webpack/assets/javascripts/react_app/components/PF4/Bookmarks/bookmarks.scss b/webpack/assets/javascripts/react_app/components/PF4/Bookmarks/bookmarks.scss index b41b45aad743..e473a8eb10cc 100644 --- a/webpack/assets/javascripts/react_app/components/PF4/Bookmarks/bookmarks.scss +++ b/webpack/assets/javascripts/react_app/components/PF4/Bookmarks/bookmarks.scss @@ -1,4 +1,4 @@ -@import '~@theforeman/vendor/scss/variables'; +@import 'node_modules/@theforeman/vendor/scss/variables'; .bookmarks-dropdown-item { word-break: break-word; diff --git a/webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrength.scss b/webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrength.scss index db05e547a3c1..33411cb7a70b 100644 --- a/webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrength.scss +++ b/webpack/assets/javascripts/react_app/components/PasswordStrength/PasswordStrength.scss @@ -1,4 +1,4 @@ -@import "~@theforeman/vendor/scss/variables"; +@import "node_modules/@theforeman/vendor/scss/variables"; @import '../../common/colors.scss'; .ReactPasswordStrength { diff --git a/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss b/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss index 5754da7f48a6..2f849d93537f 100644 --- a/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss +++ b/webpack/assets/javascripts/react_app/components/SearchBar/SearchBar.scss @@ -1,4 +1,4 @@ -@import '~@theforeman/vendor/scss/variables'; +@import 'node_modules/@theforeman/vendor/scss/variables'; .autocomplete-search { width: 100%; diff --git a/webpack/assets/javascripts/react_app/components/common/forms/DateTime/DateTimeOverrides.scss b/webpack/assets/javascripts/react_app/components/common/forms/DateTime/DateTimeOverrides.scss index 31c6f3a6c933..c7c4118fbcff 100644 --- a/webpack/assets/javascripts/react_app/components/common/forms/DateTime/DateTimeOverrides.scss +++ b/webpack/assets/javascripts/react_app/components/common/forms/DateTime/DateTimeOverrides.scss @@ -1,4 +1,4 @@ -@import "~@theforeman/vendor/scss/variables"; +@import "node_modules/@theforeman/vendor/scss/variables"; $screen-md: 992px !default; $screen-md-min: $screen-md !default; diff --git a/webpack/assets/javascripts/react_app/components/common/forms/NumericInput.scss b/webpack/assets/javascripts/react_app/components/common/forms/NumericInput.scss index 1e06824d4cd7..4dac7c188b6a 100644 --- a/webpack/assets/javascripts/react_app/components/common/forms/NumericInput.scss +++ b/webpack/assets/javascripts/react_app/components/common/forms/NumericInput.scss @@ -1,5 +1,5 @@ -@import "~@theforeman/vendor/scss/variables"; -@import "~@theforeman/vendor/scss/mixins"; +@import "node_modules/@theforeman/vendor/scss/variables"; +@import "node_modules/@theforeman/vendor/scss/mixins"; .foreman-numeric-input { position: relative;