aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-05-29 17:00:54 +0200
committerSonarTech <sonartech@sonarsource.com>2018-05-29 20:20:47 +0200
commit95220229b1d52f0acd4f1c0d4358e9fed610c3ee (patch)
tree37ce44f787c6a22aca324047efbe8bcb41b38689
parent9c10956d8a65e1e3a851691d69cee367ac4e0869 (diff)
downloadsonarqube-95220229b1d52f0acd4f1c0d4358e9fed610c3ee.tar.gz
sonarqube-95220229b1d52f0acd4f1c0d4358e9fed610c3ee.zip
SONAR-10675 Decrease JavaScript boot-up time (#283)
-rw-r--r--server/sonar-bitbucketcloud/.babelrc51
-rw-r--r--server/sonar-bitbucketcloud/package.json1
-rw-r--r--server/sonar-bitbucketcloud/yarn.lock35
-rw-r--r--server/sonar-vsts/.babelrc51
-rw-r--r--server/sonar-vsts/package.json1
-rw-r--r--server/sonar-vsts/yarn.lock37
-rw-r--r--server/sonar-web/.babelrc51
-rw-r--r--server/sonar-web/config/webpack.config.js20
-rw-r--r--server/sonar-web/package.json2
-rw-r--r--server/sonar-web/src/main/js/app/components/AdminContainer.tsx27
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/utils/startReactApp.js85
-rw-r--r--server/sonar-web/src/main/js/apps/organizations/routes.ts57
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/routes.js30
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap249
-rw-r--r--server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/controls/DateInput.tsx10
-rw-r--r--server/sonar-web/src/main/js/components/controls/Select.tsx18
-rw-r--r--server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx16
-rw-r--r--server/sonar-web/src/main/js/components/docs/DocInclude.tsx4
-rw-r--r--server/sonar-web/src/main/js/components/docs/DocTooltip.tsx20
-rw-r--r--server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap12
-rw-r--r--server/sonar-web/src/main/js/components/ui/CoverageRating.tsx4
-rw-r--r--server/sonar-web/src/main/js/helpers/dates.ts14
-rw-r--r--server/sonar-web/yarn.lock41
-rw-r--r--tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java2
29 files changed, 504 insertions, 349 deletions
diff --git a/server/sonar-bitbucketcloud/.babelrc b/server/sonar-bitbucketcloud/.babelrc
index 2962b9304d5..a14ae9bb095 100644
--- a/server/sonar-bitbucketcloud/.babelrc
+++ b/server/sonar-bitbucketcloud/.babelrc
@@ -1,40 +1,35 @@
{
"presets": [
- ["env", {
- "modules": false,
- "targets": {
- "browsers": [
- "last 3 Chrome versions",
- "last 3 Firefox versions",
- "last 3 Safari versions",
- "last 3 Edge versions",
- "IE 11"
- ]
- },
- "useBuiltIns": true
- }],
+ [
+ "env",
+ {
+ "modules": false,
+ "targets": {
+ "browsers": [
+ "last 3 Chrome versions",
+ "last 3 Firefox versions",
+ "last 3 Safari versions",
+ "last 3 Edge versions",
+ "IE 11"
+ ]
+ },
+ "useBuiltIns": true
+ }
+ ],
"react"
],
"plugins": [
"transform-class-properties",
- ["transform-object-rest-spread", {
- // use built-in `Object.assign`
- "useBuiltIns": true
- }]
+ // use built-in `Object.assign`
+ ["transform-object-rest-spread", { "useBuiltIns": true }],
+ "lodash"
],
"env": {
"production": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-constant-elements"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-constant-elements"]
},
"development": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-jsx-source",
- "transform-react-jsx-self"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-jsx-source", "transform-react-jsx-self"]
},
"test": {
"plugins": [
@@ -45,7 +40,5 @@
]
}
},
- "ignore": [
- "**/libs/**"
- ]
+ "ignore": ["**/libs/**"]
}
diff --git a/server/sonar-bitbucketcloud/package.json b/server/sonar-bitbucketcloud/package.json
index a703523cb44..a73c2d1c77c 100644
--- a/server/sonar-bitbucketcloud/package.json
+++ b/server/sonar-bitbucketcloud/package.json
@@ -36,6 +36,7 @@
"babel-jest": "22.4.3",
"babel-loader": "7.1.4",
"babel-plugin-dynamic-import-node": "1.2.0",
+ "babel-plugin-lodash": "3.3.2",
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
diff --git a/server/sonar-bitbucketcloud/yarn.lock b/server/sonar-bitbucketcloud/yarn.lock
index 2ba27285585..4064a564d36 100644
--- a/server/sonar-bitbucketcloud/yarn.lock
+++ b/server/sonar-bitbucketcloud/yarn.lock
@@ -751,6 +751,13 @@ babel-helper-hoist-variables@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
+babel-helper-module-imports@^7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz#e15764e3af9c8e11810c09f78f498a2bdc71585a"
+ dependencies:
+ babel-types "7.0.0-beta.3"
+ lodash "^4.2.0"
+
babel-helper-optimise-call-expression@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
@@ -848,6 +855,16 @@ babel-plugin-jest-hoist@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.3.tgz#7d8bcccadc2667f96a0dcc6afe1891875ee6c14a"
+babel-plugin-lodash@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.2.tgz#da3a5b49ba27447f54463f6c4fa81396ccdd463f"
+ dependencies:
+ babel-helper-module-imports "^7.0.0-beta.3"
+ babel-types "^6.26.0"
+ glob "^7.1.1"
+ lodash "^4.17.4"
+ require-package-name "^2.0.1"
+
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@@ -1263,6 +1280,14 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
invariant "^2.2.2"
lodash "^4.17.4"
+babel-types@7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.3.tgz#cd927ca70e0ae8ab05f4aab83778cfb3e6eb20b4"
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^2.0.0"
+
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
@@ -4786,7 +4811,7 @@ lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
-lodash@4.17.10, lodash@^4.17.10, lodash@^4.17.5:
+lodash@4.17.10, lodash@^4.17.10, lodash@^4.17.5, lodash@^4.2.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
@@ -6610,6 +6635,10 @@ require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+require-package-name@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
+
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
@@ -7390,6 +7419,10 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
diff --git a/server/sonar-vsts/.babelrc b/server/sonar-vsts/.babelrc
index 2962b9304d5..a14ae9bb095 100644
--- a/server/sonar-vsts/.babelrc
+++ b/server/sonar-vsts/.babelrc
@@ -1,40 +1,35 @@
{
"presets": [
- ["env", {
- "modules": false,
- "targets": {
- "browsers": [
- "last 3 Chrome versions",
- "last 3 Firefox versions",
- "last 3 Safari versions",
- "last 3 Edge versions",
- "IE 11"
- ]
- },
- "useBuiltIns": true
- }],
+ [
+ "env",
+ {
+ "modules": false,
+ "targets": {
+ "browsers": [
+ "last 3 Chrome versions",
+ "last 3 Firefox versions",
+ "last 3 Safari versions",
+ "last 3 Edge versions",
+ "IE 11"
+ ]
+ },
+ "useBuiltIns": true
+ }
+ ],
"react"
],
"plugins": [
"transform-class-properties",
- ["transform-object-rest-spread", {
- // use built-in `Object.assign`
- "useBuiltIns": true
- }]
+ // use built-in `Object.assign`
+ ["transform-object-rest-spread", { "useBuiltIns": true }],
+ "lodash"
],
"env": {
"production": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-constant-elements"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-constant-elements"]
},
"development": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-jsx-source",
- "transform-react-jsx-self"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-jsx-source", "transform-react-jsx-self"]
},
"test": {
"plugins": [
@@ -45,7 +40,5 @@
]
}
},
- "ignore": [
- "**/libs/**"
- ]
+ "ignore": ["**/libs/**"]
}
diff --git a/server/sonar-vsts/package.json b/server/sonar-vsts/package.json
index 89d6479ef8e..0a03b0fed1f 100644
--- a/server/sonar-vsts/package.json
+++ b/server/sonar-vsts/package.json
@@ -25,6 +25,7 @@
"babel-jest": "22.0.6",
"babel-loader": "7.1.4",
"babel-plugin-dynamic-import-node": "1.1.0",
+ "babel-plugin-lodash": "3.3.2",
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-class-properties": "6.22.0",
"babel-plugin-transform-object-rest-spread": "6.26.0",
diff --git a/server/sonar-vsts/yarn.lock b/server/sonar-vsts/yarn.lock
index 8b3d6df8060..093fd074912 100644
--- a/server/sonar-vsts/yarn.lock
+++ b/server/sonar-vsts/yarn.lock
@@ -536,6 +536,13 @@ babel-helper-hoist-variables@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
+babel-helper-module-imports@^7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz#e15764e3af9c8e11810c09f78f498a2bdc71585a"
+ dependencies:
+ babel-types "7.0.0-beta.3"
+ lodash "^4.2.0"
+
babel-helper-optimise-call-expression@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
@@ -633,6 +640,16 @@ babel-plugin-jest-hoist@^22.4.1:
version "22.4.1"
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.1.tgz#d712fe5da8b6965f3191dacddbefdbdf4fb66d63"
+babel-plugin-lodash@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.2.tgz#da3a5b49ba27447f54463f6c4fa81396ccdd463f"
+ dependencies:
+ babel-helper-module-imports "^7.0.0-beta.3"
+ babel-types "^6.26.0"
+ glob "^7.1.1"
+ lodash "^4.17.4"
+ require-package-name "^2.0.1"
+
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@@ -1031,6 +1048,14 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
invariant "^2.2.2"
lodash "^4.17.4"
+babel-types@7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.3.tgz#cd927ca70e0ae8ab05f4aab83778cfb3e6eb20b4"
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^2.0.0"
+
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
@@ -4471,6 +4496,10 @@ lodash@4.17.4, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, l
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+lodash@^4.2.0:
+ version "4.17.10"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
log-symbols@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
@@ -6221,6 +6250,10 @@ require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+require-package-name@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
+
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
@@ -6969,6 +7002,10 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
diff --git a/server/sonar-web/.babelrc b/server/sonar-web/.babelrc
index 2962b9304d5..a14ae9bb095 100644
--- a/server/sonar-web/.babelrc
+++ b/server/sonar-web/.babelrc
@@ -1,40 +1,35 @@
{
"presets": [
- ["env", {
- "modules": false,
- "targets": {
- "browsers": [
- "last 3 Chrome versions",
- "last 3 Firefox versions",
- "last 3 Safari versions",
- "last 3 Edge versions",
- "IE 11"
- ]
- },
- "useBuiltIns": true
- }],
+ [
+ "env",
+ {
+ "modules": false,
+ "targets": {
+ "browsers": [
+ "last 3 Chrome versions",
+ "last 3 Firefox versions",
+ "last 3 Safari versions",
+ "last 3 Edge versions",
+ "IE 11"
+ ]
+ },
+ "useBuiltIns": true
+ }
+ ],
"react"
],
"plugins": [
"transform-class-properties",
- ["transform-object-rest-spread", {
- // use built-in `Object.assign`
- "useBuiltIns": true
- }]
+ // use built-in `Object.assign`
+ ["transform-object-rest-spread", { "useBuiltIns": true }],
+ "lodash"
],
"env": {
"production": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-constant-elements"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-constant-elements"]
},
"development": {
- "plugins": [
- "syntax-dynamic-import",
- "transform-react-jsx-source",
- "transform-react-jsx-self"
- ]
+ "plugins": ["syntax-dynamic-import", "transform-react-jsx-source", "transform-react-jsx-self"]
},
"test": {
"plugins": [
@@ -45,7 +40,5 @@
]
}
},
- "ignore": [
- "**/libs/**"
- ]
+ "ignore": ["**/libs/**"]
}
diff --git a/server/sonar-web/config/webpack.config.js b/server/sonar-web/config/webpack.config.js
index c5439551c5c..30cccdbd7ae 100644
--- a/server/sonar-web/config/webpack.config.js
+++ b/server/sonar-web/config/webpack.config.js
@@ -23,6 +23,7 @@ const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+const LodashPlugin = require('lodash-webpack-plugin');
const webpack = require('webpack');
const InterpolateHtmlPlugin = require('./InterpolateHtmlPlugin');
const paths = require('./paths');
@@ -77,7 +78,6 @@ module.exports = ({ production = true }) => ({
test: /\.md$/,
use: 'raw-loader'
},
- { test: require.resolve('lodash'), loader: 'expose-loader?_' },
{ test: require.resolve('react'), loader: 'expose-loader?React' },
{ test: require.resolve('react-dom'), loader: 'expose-loader?ReactDOM' },
{
@@ -113,6 +113,15 @@ module.exports = ({ production = true }) => ({
chunkFilename: 'css/[name].[chunkhash:8].chunk.css'
}),
+ new LodashPlugin({
+ // keep these features
+ // https://github.com/lodash/lodash-webpack-plugin#feature-sets
+ shorthands: true,
+ collections: true,
+ memoizing: true,
+ flattening: true
+ }),
+
new HtmlWebpackPlugin({
inject: false,
template: paths.appHtml,
@@ -126,5 +135,12 @@ module.exports = ({ production = true }) => ({
].filter(Boolean),
optimization: {
splitChunks: { chunks: 'all' }
- }
+ },
+ performance: production
+ ? {
+ hints: 'error',
+ maxEntrypointSize: 700000, // ~700kb, recommended: 250kb
+ maxAssetSize: 400000 // ~400kb, recommended: 250kb
+ }
+ : undefined
});
diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json
index fbf2659e4b7..b199b8a9565 100644
--- a/server/sonar-web/package.json
+++ b/server/sonar-web/package.json
@@ -63,6 +63,7 @@
"babel-jest": "22.4.3",
"babel-loader": "7.1.4",
"babel-plugin-dynamic-import-node": "1.2.0",
+ "babel-plugin-lodash": "3.3.2",
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-class-properties": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "6.26.0",
@@ -93,6 +94,7 @@
"html-webpack-plugin": "3.2.0",
"jest": "22.4.3",
"lint-staged": "4.3.0",
+ "lodash-webpack-plugin": "0.11.5",
"mini-css-extract-plugin": "0.4.0",
"postcss-calc": "6.0.1",
"postcss-custom-properties": "6.2.0",
diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
index 20284555423..c81e450022d 100644
--- a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
@@ -41,23 +41,29 @@ import { Extension } from '../types';
import { PluginPendingResult } from '../../api/plugins';
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization';
-interface Props {
+interface StateProps {
appState: {
adminPages: Extension[];
organizationsEnabled: boolean;
version: string;
};
- editionsUrl: string;
editionStatus?: EditionStatus;
+ editionsUrl: string;
+ pendingPlugins: PluginPendingResult;
+}
+
+interface DispatchProps {
fetchEditions: (url: string, version: string) => void;
fetchPendingPlugins: () => void;
- location: {};
- pendingPlugins: PluginPendingResult;
setAdminPages: (adminPages: Extension[]) => void;
setEditionStatus: (editionStatus: EditionStatus) => void;
}
-class AdminContainer extends React.PureComponent<Props> {
+interface OwnProps {
+ location: {};
+}
+
+class AdminContainer extends React.PureComponent<StateProps & DispatchProps & OwnProps> {
static contextTypes = {
canAdmin: PropTypes.bool.isRequired
};
@@ -105,13 +111,18 @@ class AdminContainer extends React.PureComponent<Props> {
}
}
-const mapStateToProps = (state: any) => ({
+const mapStateToProps = (state: any): StateProps => ({
appState: getAppState(state),
editionStatus: getMarketplaceEditionStatus(state),
editionsUrl: (getGlobalSettingValue(state, 'sonar.editions.jsonUrl') || {}).value,
pendingPlugins: getMarketplacePendingPlugins(state)
});
-const mapDispatchToProps = { setAdminPages, setEditionStatus, fetchEditions, fetchPendingPlugins };
+const mapDispatchToProps: DispatchProps = {
+ setAdminPages,
+ setEditionStatus,
+ fetchEditions,
+ fetchPendingPlugins
+};
-export default connect(mapStateToProps, mapDispatchToProps)(AdminContainer as any);
+export default connect(mapStateToProps, mapDispatchToProps)(AdminContainer);
diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx b/server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx
index 6dd0208f57a..ad0c7d3b84d 100644
--- a/server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx
+++ b/server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { getYear } from 'date-fns';
+import * as getYear from 'date-fns/get_year';
import { translate } from '../../helpers/l10n';
export default function GlobalFooterSonarCloud() {
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx
index 27ba87d8e89..1583bd701c1 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx
@@ -21,9 +21,7 @@ import * as React from 'react';
import { shallow } from 'enzyme';
import GlobalFooterSonarCloud from '../GlobalFooterSonarCloud';
-jest.mock('date-fns', () => ({
- getYear: jest.fn(() => 2018)
-}));
+jest.mock('date-fns/get_year', () => jest.fn(() => 2018));
it('should render correctly', () => {
expect(shallow(<GlobalFooterSonarCloud />)).toMatchSnapshot();
diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx
index 9e1eabf9be6..d7525d24054 100644
--- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx
@@ -23,7 +23,6 @@ import GlobalNavBranding from './GlobalNavBranding';
import GlobalNavMenu from './GlobalNavMenu';
import GlobalNavExplore from './GlobalNavExplore';
import GlobalNavUserContainer from './GlobalNavUserContainer';
-import GlobalNavPlus from './GlobalNavPlus';
import Search from '../../search/Search';
import EmbedDocsPopupHelper from '../../embed-docs-modal/EmbedDocsPopupHelper';
import * as theme from '../../../theme';
@@ -31,12 +30,15 @@ import { isLoggedIn, CurrentUser, AppState } from '../../../types';
import OnboardingModal from '../../../../apps/tutorials/onboarding/OnboardingModal';
import NavBar from '../../../../components/nav/NavBar';
import Tooltip from '../../../../components/controls/Tooltip';
+import { lazyLoad } from '../../../../components/lazyLoad';
import { translate } from '../../../../helpers/l10n';
import { getCurrentUser, getAppState, getGlobalSettingValue } from '../../../../store/rootReducer';
import { skipOnboarding } from '../../../../store/users/actions';
import { SuggestionLink } from '../../embed-docs-modal/SuggestionsProvider';
import './GlobalNav.css';
+const GlobalNavPlus = lazyLoad(() => import('./GlobalNavPlus'));
+
interface StateProps {
appState: AppState;
currentUser: CurrentUser;
diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.js b/server/sonar-web/src/main/js/app/utils/startReactApp.js
index a013773e344..6d143225d4a 100644
--- a/server/sonar-web/src/main/js/app/utils/startReactApp.js
+++ b/server/sonar-web/src/main/js/app/utils/startReactApp.js
@@ -24,24 +24,10 @@ import { Router, Route, IndexRoute, Redirect } from 'react-router';
import { Provider } from 'react-redux';
import getStore from './getStore';
import getHistory from './getHistory';
-import AppContextContainer from '../components/AppContextContainer';
import LocalizationContainer from '../components/LocalizationContainer';
import MigrationContainer from '../components/MigrationContainer';
import App from '../components/App';
import GlobalContainer from '../components/GlobalContainer';
-import SimpleContainer from '../components/SimpleContainer';
-import SimpleSessionsContainer from '../components/SimpleSessionsContainer';
-import Landing from '../components/Landing';
-import ProjectAdminContainer from '../components/ProjectAdminContainer';
-import ProjectPageExtension from '../components/extensions/ProjectPageExtension';
-import ProjectAdminPageExtension from '../components/extensions/ProjectAdminPageExtension';
-import PortfoliosPage from '../components/extensions/PortfoliosPage';
-import AdminContainer from '../components/AdminContainer';
-import GlobalPageExtension from '../components/extensions/GlobalPageExtension';
-import GlobalAdminPageExtension from '../components/extensions/GlobalAdminPageExtension';
-import MarkdownHelp from '../components/MarkdownHelp';
-import NotFound from '../components/NotFound';
-import OnboardingPage from '../../apps/tutorials/onboarding/OnboardingPage';
import aboutRoutes from '../../apps/about/routes';
import accountRoutes from '../../apps/account/routes';
import backgroundTasksRoutes from '../../apps/background-tasks/routes';
@@ -63,7 +49,6 @@ import organizationsRoutes from '../../apps/organizations/routes';
import permissionTemplatesRoutes from '../../apps/permission-templates/routes';
import portfolioRoutes from '../../apps/portfolio/routes';
import projectActivityRoutes from '../../apps/projectActivity/routes';
-import projectAdminRoutes from '../../apps/project-admin/routes';
import projectBranchesRoutes from '../../apps/projectBranches/routes';
import projectQualityGateRoutes from '../../apps/projectQualityGate/routes';
import projectQualityProfilesRoutes from '../../apps/projectQualityProfiles/routes';
@@ -150,23 +135,26 @@ const startReactApp = () => {
<Redirect from="/view" to="/portfolio" />
<Redirect from="/users" to="/admin/users" />
- <Route path="markdown/help" component={MarkdownHelp} />
+ <Route
+ path="markdown/help"
+ component={lazyLoad(() => import('../components/MarkdownHelp'))}
+ />
<Route component={LocalizationContainer}>
- <Route component={SimpleContainer}>
+ <Route component={lazyLoad(() => import('../components/SimpleContainer'))}>
<Route path="maintenance">{maintenanceRoutes}</Route>
<Route path="setup">{setupRoutes}</Route>
</Route>
<Route component={MigrationContainer}>
- <Route component={AppContextContainer}>
- <Route component={SimpleSessionsContainer}>
+ <Route component={lazyLoad(() => import('../components/AppContextContainer'))}>
+ <Route component={lazyLoad(() => import('../components/SimpleSessionsContainer'))}>
<Route path="/sessions" childRoutes={sessionsRoutes} />
</Route>
</Route>
<Route path="/" component={App}>
- <IndexRoute component={Landing} />
+ <IndexRoute component={lazyLoad(() => import('../components/Landing'))} />
<Route component={GlobalContainer}>
<Route path="about" childRoutes={aboutRoutes} />
@@ -178,13 +166,24 @@ const startReactApp = () => {
<Route path="issues" component={ExploreIssues} />
<Route path="projects" component={ExploreProjects} />
</Route>
- <Route path="extension/:pluginKey/:extensionKey" component={GlobalPageExtension} />
+ <Route
+ path="extension/:pluginKey/:extensionKey"
+ component={lazyLoad(() => import('../components/extensions/GlobalPageExtension'))}
+ />
<Route path="issues" component={IssuesPageSelector} />
- <Route path="onboarding" component={OnboardingPage} />
+ <Route
+ path="onboarding"
+ component={lazyLoad(() =>
+ import('../../apps/tutorials/onboarding/OnboardingPage')
+ )}
+ />
<Route path="organizations" childRoutes={organizationsRoutes} />
<Route path="projects" childRoutes={projectsRoutes} />
<Route path="quality_gates" childRoutes={qualityGatesRoutes} />
- <Route path="portfolios" component={PortfoliosPage} />
+ <Route
+ path="portfolios"
+ component={lazyLoad(() => import('../components/extensions/PortfoliosPage'))}
+ />
<Route path="profiles" childRoutes={qualityProfilesRoutes} />
<Route path="web_api" childRoutes={webAPIRoutes} />
@@ -196,7 +195,9 @@ const startReactApp = () => {
<Route path="project/activity" childRoutes={projectActivityRoutes} />
<Route
path="project/extension/:pluginKey/:extensionKey"
- component={ProjectPageExtension}
+ component={lazyLoad(() =>
+ import('../components/extensions/ProjectPageExtension')
+ )}
/>
<Route path="project/issues" component={Issues} />
<Route path="project/quality_gate" childRoutes={projectQualityGateRoutes} />
@@ -204,25 +205,44 @@ const startReactApp = () => {
path="project/quality_profiles"
childRoutes={projectQualityProfilesRoutes}
/>
- <Route component={ProjectAdminContainer}>
+ <Route component={lazyLoad(() => import('../components/ProjectAdminContainer'))}>
<Route path="custom_measures" childRoutes={customMeasuresRoutes} />
<Route
path="project/admin/extension/:pluginKey/:extensionKey"
- component={ProjectAdminPageExtension}
+ component={lazyLoad(() =>
+ import('../components/extensions/ProjectAdminPageExtension')
+ )}
/>
<Route path="project/background_tasks" childRoutes={backgroundTasksRoutes} />
<Route path="project/branches" childRoutes={projectBranchesRoutes} />
<Route path="project/settings" childRoutes={settingsRoutes} />
<Route path="project_roles" childRoutes={projectPermissionsRoutes} />
<Route path="project/webhooks" childRoutes={webhooksRoutes} />
+ <Route
+ path="project/deletion"
+ component={lazyLoad(() =>
+ import('../../apps/project-admin/deletion/Deletion')
+ )}
+ />
+ <Route
+ path="project/links"
+ component={lazyLoad(() => import('../../apps/project-admin/links/Links'))}
+ />
+ <Route
+ path="project/key"
+ component={lazyLoad(() => import('../../apps/project-admin/key/Key'))}
+ />
</Route>
- {projectAdminRoutes}
</Route>
- <Route component={AdminContainer} path="admin">
+ <Route
+ component={lazyLoad(() => import('../components/AdminContainer'))}
+ path="admin">
<Route
path="extension/:pluginKey/:extensionKey"
- component={GlobalAdminPageExtension}
+ component={lazyLoad(() =>
+ import('../components/extensions/GlobalAdminPageExtension')
+ )}
/>
<Route path="background_tasks" childRoutes={backgroundTasksRoutes} />
<Route path="custom_metrics" childRoutes={customMetricsRoutes} />
@@ -238,8 +258,11 @@ const startReactApp = () => {
<Route path="webhooks" childRoutes={webhooksRoutes} />
</Route>
</Route>
- <Route path="not_found" component={NotFound} />
- <Route path="*" component={NotFound} />
+ <Route
+ path="not_found"
+ component={lazyLoad(() => import('../components/NotFound'))}
+ />
+ <Route path="*" component={lazyLoad(() => import('../components/NotFound'))} />
</Route>
</Route>
</Route>
diff --git a/server/sonar-web/src/main/js/apps/organizations/routes.ts b/server/sonar-web/src/main/js/apps/organizations/routes.ts
index e267926dce1..02c2bdaec00 100644
--- a/server/sonar-web/src/main/js/apps/organizations/routes.ts
+++ b/server/sonar-web/src/main/js/apps/organizations/routes.ts
@@ -18,28 +18,18 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { RouterState, RedirectFunction } from 'react-router';
-import OrganizationPageContainer from './components/OrganizationPage';
-import OrganizationContainer from './components/OrganizationContainer';
-import OrganizationProjects from './components/OrganizationProjects';
-import OrganizationAdminContainer from './components/OrganizationAdminContainer';
-import OrganizationEdit from './components/OrganizationEdit';
-import OrganizationMembersContainer from './components/OrganizationMembersContainer';
-import OrganizationDelete from './components/OrganizationDelete';
-import GlobalPermissionsApp from '../permissions/global/components/App';
-import PermissionTemplateApp from '../permission-templates/components/AppContainer';
-import ProjectManagementApp from '../projectsManagement/AppContainer';
import codingRulesRoutes from '../coding-rules/routes';
import qualityGatesRoutes from '../quality-gates/routes';
import qualityProfilesRoutes from '../quality-profiles/routes';
import webhooksRoutes from '../webhooks/routes';
-import Issues from '../issues/components/AppContainer';
-import GroupsApp from '../groups/components/App';
-import OrganizationPageExtension from '../../app/components/extensions/OrganizationPageExtension';
+import { lazyLoad } from '../../components/lazyLoad';
+
+const OrganizationContainer = lazyLoad(() => import('./components/OrganizationContainer'));
const routes = [
{
path: ':organizationKey',
- component: OrganizationPageContainer,
+ component: lazyLoad(() => import('./components/OrganizationPage')),
childRoutes: [
{
indexRoute: {
@@ -52,19 +42,23 @@ const routes = [
{
path: 'projects',
component: OrganizationContainer,
- childRoutes: [{ indexRoute: { component: OrganizationProjects } }]
+ childRoutes: [
+ { indexRoute: { component: lazyLoad(() => import('./components/OrganizationProjects')) } }
+ ]
},
{
path: 'issues',
component: OrganizationContainer,
- childRoutes: [{ indexRoute: { component: Issues } }]
+ childRoutes: [
+ { indexRoute: { component: lazyLoad(() => import('../issues/components/AppContainer')) } }
+ ]
},
{
path: 'members',
- component: OrganizationMembersContainer
+ component: lazyLoad(() => import('./components/OrganizationMembersContainer'))
},
{
- path: 'rules',
+ path: 'rules',
component: OrganizationContainer,
childRoutes: codingRulesRoutes
},
@@ -78,18 +72,29 @@ const routes = [
childRoutes: qualityGatesRoutes
},
{
- component: OrganizationAdminContainer,
+ component: lazyLoad(() => import('./components/OrganizationAdminContainer')),
childRoutes: [
- { path: 'delete', component: OrganizationDelete },
- { path: 'edit', component: OrganizationEdit },
- { path: 'groups', component: GroupsApp },
- { path: 'permissions', component: GlobalPermissionsApp },
- { path: 'permission_templates', component: PermissionTemplateApp },
- { path: 'projects_management', component: ProjectManagementApp },
+ { path: 'delete', component: lazyLoad(() => import('./components/OrganizationDelete')) },
+ { path: 'edit', component: lazyLoad(() => import('./components/OrganizationEdit')) },
+ { path: 'groups', component: lazyLoad(() => import('../groups/components/App')) },
+ {
+ path: 'permissions',
+ component: lazyLoad(() => import('../permissions/global/components/App'))
+ },
+ {
+ path: 'permission_templates',
+ component: lazyLoad(() => import('../permission-templates/components/AppContainer'))
+ },
+ {
+ path: 'projects_management',
+ component: lazyLoad(() => import('../projectsManagement/AppContainer'))
+ },
{ path: 'webhooks', childRoutes: webhooksRoutes },
{
path: 'extension/:pluginKey/:extensionKey',
- component: OrganizationPageExtension
+ component: lazyLoad(() =>
+ import('../../app/components/extensions/OrganizationPageExtension')
+ )
}
]
}
diff --git a/server/sonar-web/src/main/js/apps/project-admin/routes.js b/server/sonar-web/src/main/js/apps/project-admin/routes.js
deleted file mode 100644
index 78c051e7f89..00000000000
--- a/server/sonar-web/src/main/js/apps/project-admin/routes.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-import { Route } from 'react-router';
-import Deletion from './deletion/Deletion';
-import Links from './links/Links';
-import Key from './key/Key';
-
-export default [
- <Route key="deletion" path="project/deletion" component={Deletion} />,
- <Route key="links" path="project/links" component={Links} />,
- <Route key="key" path="project/key" component={Key} />
-];
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx
index 054f9777d03..2c9ab530964 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx
@@ -20,7 +20,8 @@
import * as React from 'react';
import { Link } from 'react-router';
import { sortBy } from 'lodash';
-import { isSameMinute, startOfMinute } from 'date-fns';
+import * as isSameMinute from 'date-fns/is_same_minute';
+import * as startOfMinute from 'date-fns/start_of_minute';
import ChangesList from './ChangesList';
import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
import { translate } from '../../../helpers/l10n';
diff --git a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap
index 3f1d39e377e..4ff55018414 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap
@@ -80,40 +80,11 @@ exports[`works with existing organization 1`] = `
]
}
>
- <Select
- arrowRenderer={[Function]}
- autosize={true}
- backspaceRemoves={true}
- backspaceToRemoveMessage="Press backspace to remove {label}"
+ <LazyLoader
className="input-super-large"
- clearAllText="Clear all"
clearRenderer={[Function]}
- clearValueText="Clear value"
clearable={false}
- closeOnSelect={true}
- deleteRemoves={true}
- delimiter=","
- disabled={false}
- escapeClearsValue={true}
- filterOptions={[Function]}
- ignoreAccents={true}
- ignoreCase={true}
- inputProps={Object {}}
- isLoading={false}
- joinValues={false}
- labelKey="label"
- matchPos="any"
- matchProp="any"
- menuBuffer={0}
- menuRenderer={[Function]}
- multi={false}
- noResultsText="No results found"
- onBlurResetsInput={true}
onChange={[Function]}
- onCloseResetsInput={true}
- onSelectResetsInput={true}
- openOnClick={true}
- optionComponent={[Function]}
options={
Array [
Object {
@@ -126,108 +97,156 @@ exports[`works with existing organization 1`] = `
},
]
}
- pageSize={5}
- placeholder="Select..."
- removeSelected={true}
- required={false}
- rtl={false}
- scrollMenuIntoView={true}
- searchable={true}
- simpleValue={false}
- tabSelectsValue={true}
- trimFilter={true}
- valueComponent={[Function]}
- valueKey="value"
>
- <div
- className="Select input-super-large is-searchable Select--single"
+ <Select
+ arrowRenderer={[Function]}
+ autosize={true}
+ backspaceRemoves={true}
+ backspaceToRemoveMessage="Press backspace to remove {label}"
+ className="input-super-large"
+ clearAllText="Clear all"
+ clearRenderer={[Function]}
+ clearValueText="Clear value"
+ clearable={false}
+ closeOnSelect={true}
+ deleteRemoves={true}
+ delimiter=","
+ disabled={false}
+ escapeClearsValue={true}
+ filterOptions={[Function]}
+ ignoreAccents={true}
+ ignoreCase={true}
+ inputProps={Object {}}
+ isLoading={false}
+ joinValues={false}
+ labelKey="label"
+ matchPos="any"
+ matchProp="any"
+ menuBuffer={0}
+ menuRenderer={[Function]}
+ multi={false}
+ noResultsText="No results found"
+ onBlurResetsInput={true}
+ onChange={[Function]}
+ onCloseResetsInput={true}
+ onSelectResetsInput={true}
+ openOnClick={true}
+ optionComponent={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "another",
+ "value": "another",
+ },
+ Object {
+ "label": "user",
+ "value": "user",
+ },
+ ]
+ }
+ pageSize={5}
+ placeholder="Select..."
+ removeSelected={true}
+ required={false}
+ rtl={false}
+ scrollMenuIntoView={true}
+ searchable={true}
+ simpleValue={false}
+ tabSelectsValue={true}
+ trimFilter={true}
+ valueComponent={[Function]}
+ valueKey="value"
>
<div
- className="Select-control"
- onKeyDown={[Function]}
- onMouseDown={[Function]}
- onTouchEnd={[Function]}
- onTouchMove={[Function]}
- onTouchStart={[Function]}
+ className="Select input-super-large is-searchable Select--single"
>
- <span
- className="Select-multi-value-wrapper"
- id="react-select-2--value"
+ <div
+ className="Select-control"
+ onKeyDown={[Function]}
+ onMouseDown={[Function]}
+ onTouchEnd={[Function]}
+ onTouchMove={[Function]}
+ onTouchStart={[Function]}
>
- <div
- className="Select-placeholder"
- >
- Select...
- </div>
- <AutosizeInput
- aria-activedescendant="react-select-2--value"
- aria-expanded="false"
- aria-haspopup="false"
- aria-owns=""
- className="Select-input"
- injectStyles={true}
- minWidth="5"
- onBlur={[Function]}
- onChange={[Function]}
- onFocus={[Function]}
- required={false}
- role="combobox"
- value=""
+ <span
+ className="Select-multi-value-wrapper"
+ id="react-select-2--value"
>
<div
+ className="Select-placeholder"
+ >
+ Select...
+ </div>
+ <AutosizeInput
+ aria-activedescendant="react-select-2--value"
+ aria-expanded="false"
+ aria-haspopup="false"
+ aria-owns=""
className="Select-input"
- style={
- Object {
- "display": "inline-block",
- }
- }
+ injectStyles={true}
+ minWidth="5"
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ required={false}
+ role="combobox"
+ value=""
>
- <input
- aria-activedescendant="react-select-2--value"
- aria-expanded="false"
- aria-haspopup="false"
- aria-owns=""
- onBlur={[Function]}
- onChange={[Function]}
- onFocus={[Function]}
- required={false}
- role="combobox"
- style={
- Object {
- "boxSizing": "content-box",
- "width": "5px",
- }
- }
- value=""
- />
<div
+ className="Select-input"
style={
Object {
- "height": 0,
- "left": 0,
- "overflow": "scroll",
- "position": "absolute",
- "top": 0,
- "visibility": "hidden",
- "whiteSpace": "pre",
+ "display": "inline-block",
}
}
- />
- </div>
- </AutosizeInput>
- </span>
- <span
- className="Select-arrow-zone"
- onMouseDown={[Function]}
- >
+ >
+ <input
+ aria-activedescendant="react-select-2--value"
+ aria-expanded="false"
+ aria-haspopup="false"
+ aria-owns=""
+ onBlur={[Function]}
+ onChange={[Function]}
+ onFocus={[Function]}
+ required={false}
+ role="combobox"
+ style={
+ Object {
+ "boxSizing": "content-box",
+ "width": "5px",
+ }
+ }
+ value=""
+ />
+ <div
+ style={
+ Object {
+ "height": 0,
+ "left": 0,
+ "overflow": "scroll",
+ "position": "absolute",
+ "top": 0,
+ "visibility": "hidden",
+ "whiteSpace": "pre",
+ }
+ }
+ />
+ </div>
+ </AutosizeInput>
+ </span>
<span
- className="Select-arrow"
+ className="Select-arrow-zone"
onMouseDown={[Function]}
- />
- </span>
+ >
+ <span
+ className="Select-arrow"
+ onMouseDown={[Function]}
+ />
+ </span>
+ </div>
</div>
- </div>
- </Select>
+ </Select>
+ </LazyLoader>
</Select>
</div>
</div>
diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
index 188369030f9..fc8b7686a80 100644
--- a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
+++ b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
@@ -149,7 +149,7 @@ export default class Line extends React.PureComponent<Props> {
<LineDuplications line={line} onClick={this.props.loadDuplications} />
)}
- {times(duplicationsCount).map(index => (
+ {times(duplicationsCount, index => (
<LineDuplicationBlock
duplicated={duplications.includes(index)}
index={index}
diff --git a/server/sonar-web/src/main/js/components/controls/DateInput.tsx b/server/sonar-web/src/main/js/components/controls/DateInput.tsx
index 886a43211e4..4da2144f9ac 100644
--- a/server/sonar-web/src/main/js/components/controls/DateInput.tsx
+++ b/server/sonar-web/src/main/js/components/controls/DateInput.tsx
@@ -19,12 +19,16 @@
*/
import * as React from 'react';
import * as classNames from 'classnames';
-import DayPicker, { DayModifiers, Modifier, Modifiers } from 'react-day-picker';
+import { DayModifiers, Modifier, Modifiers } from 'react-day-picker';
import { intlShape, InjectedIntlProps } from 'react-intl';
import { range } from 'lodash';
-import { addMonths, subMonths, setYear, setMonth } from 'date-fns';
+import * as addMonths from 'date-fns/add_months';
+import * as setMonth from 'date-fns/set_month';
+import * as setYear from 'date-fns/set_year';
+import * as subMonths from 'date-fns/sub_months';
import OutsideClickHandler from './OutsideClickHandler';
import Select from './Select';
+import { lazyLoad } from '../lazyLoad';
import * as theme from '../../app/theme';
import CalendarIcon from '../icons-components/CalendarIcon';
import ChevronLeftIcon from '../icons-components/ChevronLeftIcon';
@@ -35,6 +39,8 @@ import { getShortMonthName, getWeekDayName, getShortWeekDayName } from '../../he
import './DayPicker.css';
import './styles.css';
+const DayPicker = lazyLoad(() => import('react-day-picker'));
+
export interface Props {
className?: string;
currentMonth?: Date;
diff --git a/server/sonar-web/src/main/js/components/controls/Select.tsx b/server/sonar-web/src/main/js/components/controls/Select.tsx
index 8aa569de29b..aca10d86b70 100644
--- a/server/sonar-web/src/main/js/components/controls/Select.tsx
+++ b/server/sonar-web/src/main/js/components/controls/Select.tsx
@@ -18,18 +18,18 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import ReactSelect, {
- Creatable as ReactCreatable,
- Async,
- ReactSelectProps,
- ReactCreatableSelectProps,
- ReactAsyncSelectProps
-} from 'react-select';
+import { ReactSelectProps, ReactCreatableSelectProps, ReactAsyncSelectProps } from 'react-select';
import * as theme from '../../app/theme';
import ClearIcon from '../icons-components/ClearIcon';
import { ButtonIcon } from '../ui/buttons';
+import { lazyLoad } from '../lazyLoad';
import './react-select.css';
+const ReactSelectLib = import('react-select');
+const ReactSelect = lazyLoad(() => ReactSelectLib);
+const ReactCreatable = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib.Creatable })));
+const ReactAsync = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib.Async })));
+
function renderInput() {
return (
<ButtonIcon className="button-tiny spacer-left text-middle" color={theme.gray60}>
@@ -39,7 +39,7 @@ function renderInput() {
}
interface WithInnerRef {
- innerRef?: (element: ReactSelect) => void;
+ innerRef?: (element: React.Component) => void;
}
export default function Select({ innerRef, ...props }: WithInnerRef & ReactSelectProps) {
@@ -61,5 +61,5 @@ export function Creatable(props: ReactCreatableSelectProps) {
// TODO figure out why `ref` prop is incompatible
export function AsyncSelect(props: ReactAsyncSelectProps & { ref?: any }) {
- return <Async {...props} />;
+ return <ReactAsync {...props} />;
}
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
index 564f884d920..82a5894856e 100644
--- a/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
+++ b/server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
@@ -18,16 +18,20 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { subMonths, setMonth, setYear, addDays, subDays } from 'date-fns';
+import * as addDays from 'date-fns/add_days';
+import * as setMonth from 'date-fns/set_month';
+import * as setYear from 'date-fns/set_year';
+import * as subDays from 'date-fns/sub_days';
+import * as subMonths from 'date-fns/sub_months';
import DateInput, { Props } from '../DateInput';
import { shallowWithIntl } from '../../../helpers/testUtils';
import { parseDate } from '../../../helpers/dates';
-// need to mock, because react-day-picker uses `new Date()` as a default prop for `initialMonth`
-jest.mock('react-day-picker', () => ({
- // eslint-disable-next-line func-name-matching
- default: function DayPicker() {
- return null;
+jest.mock('../../lazyLoad', () => ({
+ lazyLoad: () => {
+ return function DayPicker() {
+ return null;
+ };
}
}));
diff --git a/server/sonar-web/src/main/js/components/docs/DocInclude.tsx b/server/sonar-web/src/main/js/components/docs/DocInclude.tsx
index 85298633439..d499b27c22c 100644
--- a/server/sonar-web/src/main/js/components/docs/DocInclude.tsx
+++ b/server/sonar-web/src/main/js/components/docs/DocInclude.tsx
@@ -18,7 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import DocMarkdownBlock from './DocMarkdownBlock';
+import { lazyLoad } from '../lazyLoad';
+
+const DocMarkdownBlock = lazyLoad(() => import('./DocMarkdownBlock'));
interface Props {
className?: string;
diff --git a/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx b/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx
index e064f15d2ee..c456c9ecd21 100644
--- a/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx
+++ b/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx
@@ -18,8 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import DocMarkdownBlock from './DocMarkdownBlock';
import HelpTooltip from '../controls/HelpTooltip';
+import { lazyLoad } from '../lazyLoad';
+
+const DocMarkdownBlock = lazyLoad(() => import('./DocMarkdownBlock'));
interface Props {
className?: string;
@@ -75,15 +77,15 @@ export default class DocTooltip extends React.PureComponent<Props, State> {
};
renderOverlay() {
- if (this.state.loading) {
- return (
- <div className="abs-width-300">
+ return (
+ <div className="abs-width-300">
+ {this.state.loading ? (
<i className="spinner" />
- </div>
- );
- }
-
- return <DocMarkdownBlock className="cut-margins abs-width-300" content={this.state.content} />;
+ ) : (
+ <DocMarkdownBlock className="cut-margins" content={this.state.content} />
+ )}
+ </div>
+ );
}
render() {
diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap
index cbdf355d855..cc1d24b0783 100644
--- a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap
+++ b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap
@@ -19,10 +19,14 @@ exports[`should render 2`] = `
<HelpTooltip
onShow={[Function]}
overlay={
- <DocMarkdownBlock
- className="cut-margins abs-width-300"
- content="this is *bold* text"
- />
+ <div
+ className="abs-width-300"
+ >
+ <LazyLoader
+ className="cut-margins"
+ content="this is *bold* text"
+ />
+ </div>
}
/>
`;
diff --git a/server/sonar-web/src/main/js/components/ui/CoverageRating.tsx b/server/sonar-web/src/main/js/components/ui/CoverageRating.tsx
index 10ffc9e849b..6814eea2f1d 100644
--- a/server/sonar-web/src/main/js/components/ui/CoverageRating.tsx
+++ b/server/sonar-web/src/main/js/components/ui/CoverageRating.tsx
@@ -18,9 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import DonutChart from '../charts/DonutChart';
+import { lazyLoad } from '../lazyLoad';
import * as theme from '../../app/theme';
+const DonutChart = lazyLoad(() => import('../charts/DonutChart'));
+
const SIZE_TO_WIDTH_MAPPING = { small: 16, normal: 24, big: 40, huge: 60 };
const SIZE_TO_THICKNESS_MAPPING = { small: 2, normal: 3, big: 3, huge: 4 };
diff --git a/server/sonar-web/src/main/js/helpers/dates.ts b/server/sonar-web/src/main/js/helpers/dates.ts
index f6f9167435d..b86e3685446 100644
--- a/server/sonar-web/src/main/js/helpers/dates.ts
+++ b/server/sonar-web/src/main/js/helpers/dates.ts
@@ -17,14 +17,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import {
- differenceInDays as _differenceInDays,
- differenceInSeconds as _differenceInSeconds,
- differenceInYears as _differenceInYears,
- isSameDay as _isSameDay,
- parse,
- startOfDay as _startOfDay
-} from 'date-fns';
+import * as _differenceInDays from 'date-fns/difference_in_days';
+import * as _differenceInSeconds from 'date-fns/difference_in_seconds';
+import * as _differenceInYears from 'date-fns/difference_in_years';
+import * as _isSameDay from 'date-fns/is_same_day';
+import * as _startOfDay from 'date-fns/start_of_day';
+import * as parse from 'date-fns/parse';
function pad(number: number) {
if (number < 10) {
diff --git a/server/sonar-web/yarn.lock b/server/sonar-web/yarn.lock
index 3fa52d493cc..45c78e2cf5c 100644
--- a/server/sonar-web/yarn.lock
+++ b/server/sonar-web/yarn.lock
@@ -760,6 +760,13 @@ babel-helper-hoist-variables@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
+babel-helper-module-imports@^7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz#e15764e3af9c8e11810c09f78f498a2bdc71585a"
+ dependencies:
+ babel-types "7.0.0-beta.3"
+ lodash "^4.2.0"
+
babel-helper-optimise-call-expression@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
@@ -849,6 +856,16 @@ babel-plugin-jest-hoist@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.3.tgz#7d8bcccadc2667f96a0dcc6afe1891875ee6c14a"
+babel-plugin-lodash@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.2.tgz#da3a5b49ba27447f54463f6c4fa81396ccdd463f"
+ dependencies:
+ babel-helper-module-imports "^7.0.0-beta.3"
+ babel-types "^6.26.0"
+ glob "^7.1.1"
+ lodash "^4.17.4"
+ require-package-name "^2.0.1"
+
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@@ -1252,6 +1269,14 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
invariant "^2.2.2"
lodash "^4.17.4"
+babel-types@7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.3.tgz#cd927ca70e0ae8ab05f4aab83778cfb3e6eb20b4"
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^2.0.0"
+
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
@@ -5093,6 +5118,12 @@ lodash-es@^4.17.5, lodash-es@^4.2.1:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.10.tgz#62cd7104cdf5dd87f235a837f0ede0e8e5117e05"
+lodash-webpack-plugin@0.11.5:
+ version "0.11.5"
+ resolved "https://registry.yarnpkg.com/lodash-webpack-plugin/-/lodash-webpack-plugin-0.11.5.tgz#c4bd064b4f561c3f823fa5982bdeb12c475390b9"
+ dependencies:
+ lodash "^4.17.4"
+
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
@@ -5129,7 +5160,7 @@ lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
-lodash@4.17.10, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0:
+lodash@4.17.10, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
@@ -7169,6 +7200,10 @@ require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+require-package-name@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
+
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
@@ -7965,6 +8000,10 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java
index a6789d3c74d..50d4849035c 100644
--- a/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java
@@ -102,7 +102,7 @@ public class ProjectKeyUpdatePageTest {
$(".modal").shouldNotBe(visible);
- tester.openBrowser().openProjectKey("another");
+ openPage("another");
assertThat(url()).endsWith("/project/key?id=another");
}