]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10675 Decrease JavaScript boot-up time (#283)
authorStas Vilchik <stas.vilchik@sonarsource.com>
Tue, 29 May 2018 15:00:54 +0000 (17:00 +0200)
committerSonarTech <sonartech@sonarsource.com>
Tue, 29 May 2018 18:20:47 +0000 (20:20 +0200)
29 files changed:
server/sonar-bitbucketcloud/.babelrc
server/sonar-bitbucketcloud/package.json
server/sonar-bitbucketcloud/yarn.lock
server/sonar-vsts/.babelrc
server/sonar-vsts/package.json
server/sonar-vsts/yarn.lock
server/sonar-web/.babelrc
server/sonar-web/config/webpack.config.js
server/sonar-web/package.json
server/sonar-web/src/main/js/app/components/AdminContainer.tsx
server/sonar-web/src/main/js/app/components/GlobalFooterSonarCloud.tsx
server/sonar-web/src/main/js/app/components/__tests__/GlobalFooterSonarCloud-test.tsx
server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx
server/sonar-web/src/main/js/app/utils/startReactApp.js
server/sonar-web/src/main/js/apps/organizations/routes.ts
server/sonar-web/src/main/js/apps/project-admin/routes.js [deleted file]
server/sonar-web/src/main/js/apps/quality-profiles/changelog/Changelog.tsx
server/sonar-web/src/main/js/apps/tutorials/onboarding/__tests__/__snapshots__/OrganizationStep-test.js.snap
server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx
server/sonar-web/src/main/js/components/controls/DateInput.tsx
server/sonar-web/src/main/js/components/controls/Select.tsx
server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
server/sonar-web/src/main/js/components/docs/DocInclude.tsx
server/sonar-web/src/main/js/components/docs/DocTooltip.tsx
server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap
server/sonar-web/src/main/js/components/ui/CoverageRating.tsx
server/sonar-web/src/main/js/helpers/dates.ts
server/sonar-web/yarn.lock
tests/src/test/java/org/sonarqube/tests/project/ProjectKeyUpdatePageTest.java

index 2962b9304d526a618ac3472a356b3e16a61c9646..a14ae9bb095a307312159e7b0d15ecb7b634712f 100644 (file)
@@ -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/**"]
 }
index a703523cb44d536ad47b20d6949830b240ca10ac..a73c2d1c77c91ca8fa0c40766a352ec0e2a3f05f 100644 (file)
@@ -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",
index 2ba2728558508a3b16a35e0c262f04c8ca1652b8..4064a564d3694298ccf30d01b1d4edee6b1b912f 100644 (file)
@@ -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"
index 2962b9304d526a618ac3472a356b3e16a61c9646..a14ae9bb095a307312159e7b0d15ecb7b634712f 100644 (file)
@@ -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/**"]
 }
index 89d6479ef8e6493b923066e1128022a3dddbb7e0..0a03b0fed1facf71beae84f15d6449eb72f6836d 100644 (file)
@@ -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",
index 8b3d6df8060657de01fb748b572030f41862f363..093fd0749123fd80f3a1ae6cdc3a120d7c166bd4 100644 (file)
@@ -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"
index 2962b9304d526a618ac3472a356b3e16a61c9646..a14ae9bb095a307312159e7b0d15ecb7b634712f 100644 (file)
@@ -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/**"]
 }
index c5439551c5c2b19e4f56d09d901970b8deb54119..30cccdbd7aeed14a366839a92505751e27bb27be 100644 (file)
@@ -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
 });
index fbf2659e4b763356ed03aa6cb45de2ba2727089d..b199b8a9565ca7cd6027c811ba59323345e7941e 100644 (file)
@@ -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",
index 20284555423425822cc6e022fde1ceaad2fe9646..c81e450022dbafb5fe3d65d4cb63ba46fe3f46dd 100644 (file)
@@ -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);
index 6dd0208f57a4aaf68c3dc5c2d20c11a47b6c8971..ad0c7d3b84df2cf9981b359f9f563f4bb61bc113 100644 (file)
@@ -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() {
index 27ba87d8e898747d8390317efb18e0aa20599a31..1583bd701c10fe3f364a551f76bcd025d6b329b3 100644 (file)
@@ -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();
index 9e1eabf9be6686b5ebae86befbaf16912067e98b..d7525d24054392e9f132f5a9badf34c0929b40d4 100644 (file)
@@ -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;
index a013773e3446d73a886aa9a9146783429760c1d0..6d143225d4a24c3de7f45e0c31b2c5615cc81d9a 100644 (file)
@@ -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>
index e267926dce1d125b2bb5b9eb7bcdc47cf01e5b88..02c2bdaec00022f2f2fa66b5ececa4156f1e8c40 100644 (file)
  * 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 (file)
index 78c051e..0000000
+++ /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} />
-];
index 054f9777d034c1b6d83037f57355da5523e084d8..2c9ab530964fbd7b2ea6e2bf5ee9b3dcd6e3fbb6 100644 (file)
@@ -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';
index 3f1d39e377ead6fea83c4eef89b22496abaaef9e..4ff55018414b23a46b76702aa177be34ccebc02a 100644 (file)
@@ -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>
index 188369030f9ad5215fe7ea63b1d8a6aa7a38282a..fc8b7686a800cb65f1194c06962c1ab857571b7d 100644 (file)
@@ -149,7 +149,7 @@ export default class Line extends React.PureComponent<Props> {
           <LineDuplications line={line} onClick={this.props.loadDuplications} />
         )}
 
-        {times(duplicationsCount).map(index => (
+        {times(duplicationsCountindex => (
           <LineDuplicationBlock
             duplicated={duplications.includes(index)}
             index={index}
index 886a43211e48e4ceb988a49ac696807ed4b43409..4da2144f9ac0af05186dfa26cbd72e2e9e23a7a9 100644 (file)
  */
 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;
index 8aa569de29bb585189ed3e69c290e47c80679ae6..aca10d86b707af8eb4401e8016fec8886db4ed75 100644 (file)
  * 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} />;
 }
index 564f884d9204f3e5c3ed2bdb0647ab049246e006..82a5894856ee8781a49202543cb1a4a8134e7fe1 100644 (file)
  * 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;
+    };
   }
 }));
 
index 85298633439c5de385442febdd6ac2cae45a30ad..d499b27c22c4ee3a2316d70030ec321201d6e5c9 100644 (file)
@@ -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;
index e064f15d2ee0a7acde5b662e41dd19043007a8be..c456c9ecd210afe4f6a69f58ac4c48105e7d2ecf 100644 (file)
  * 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() {
index cbdf355d8558ae3e2c65dbc75f437c7b76e7f53a..cc1d24b0783d91d5f3b88d008fe2f7280abd55c7 100644 (file)
@@ -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>
   }
 />
 `;
index 10ffc9e849b62cec48398aaecd6942f1b2516c6b..6814eea2f1dcaa06c3f2e9a686e93c72f103af0e 100644 (file)
  * 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 };
index f6f9167435dfe99ad1316465e8efeb216d08187c..b86e36854467f4f96657f24657878f7032e5814c 100644 (file)
  * 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) {
index 3fa52d493cc3a48aa4e1a7a1d520b818a55f74b8..45c78e2cf5ca5a1ab5697a02531c940668a2edd9 100644 (file)
@@ -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"
index a6789d3c74da216ad12ba086ddafc3ba9703ba9c..50d4849035c862d5c70757e63006a86242d2df0d 100644 (file)
@@ -102,7 +102,7 @@ public class ProjectKeyUpdatePageTest {
 
     $(".modal").shouldNotBe(visible);
 
-    tester.openBrowser().openProjectKey("another");
+    openPage("another");
     assertThat(url()).endsWith("/project/key?id=another");
   }