Repository: jhipster/generator-jhipster
Pull request #7225 (2018-03-04 15:06:50)

React polish
- Please make sure the below checklist is followed for Pull Requests.

- [ ] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green
- [ ] Tests are added where necessary
- [ ] Documentation is added/updated where necessary
- [ ] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md) are followed



Patch:
diff --git a/generators/client/files-react.js b/generators/client/files-react.js
index a218e4bfca..2f7008e8a5 100644
--- a/generators/client/files-react.js
+++ b/generators/client/files-react.js
@@ -180,24 +180,17 @@ const files = {
         {
             path: REACT_DIR,
             templates: [
-                // home module
-                'reducers/index.ts',
-                'reducers/action-type.util.ts',
-                'reducers/administration.ts',
-                'reducers/authentication.ts',
-                'reducers/layout.ts',
-                'reducers/user-management.ts',
-                'reducers/account.ts',
-                'reducers/register.ts',
-                'reducers/activate.ts',
-                'reducers/password-reset.ts'
+                'shared/reducers/index.ts',
+                'shared/reducers/action-type.util.ts',
+                'shared/reducers/authentication.ts',
+                'shared/reducers/layout.ts'
             ]
         },
         {
             condition: generator => generator.enableTranslation,
             path: REACT_DIR,
             templates: [
-                'reducers/locale.ts'
+                'shared/reducers/locale.ts'
             ]
         }
     ],
@@ -210,13 +203,17 @@ const files = {
                 { file: 'modules/account/activate/activate.tsx', method: 'processJsx' },
                 { file: 'modules/account/password/password.tsx', method: 'processJsx' },
                 { file: 'modules/account/register/register.tsx', method: 'processJsx' },
-                { file: 'modules/account/password/password-strength-bar.tsx', method: 'processJsx' },
                 { file: 'modules/account/password-reset/init/password-reset-init.tsx', method: 'processJsx' },
                 { file: 'modules/account/password-reset/finish/password-reset-finish.tsx', method: 'processJsx' },
                 // { file: 'account/password-reset/finish/_password-reset-finish.component.js', method: 'processJsx' },
-                { file: 'modules/account/settings/settings.tsx', method: 'processJsx' }
+                { file: 'modules/account/settings/settings.tsx', method: 'processJsx' },
+                'modules/account/register/register.reducer.ts',
+                'modules/account/activate/activate.reducer.ts',
+                'modules/account/password-reset/password-reset.reducer.ts',
+                'modules/account/password/password.reducer.ts',
+                'modules/account/settings/settings.reducer.ts'
             ]
-        },
+        }
         // {
         //   condition: generator => generator.authenticationType === 'session',
         //   path: REACT_DIR,
@@ -241,20 +238,6 @@ const files = {
         //             { file: 'account/social/_social-auth.component.js', method: 'processJsx' },
         //   ]
         // },
-        {
-            condition: generator => generator.useSass,
-            path: REACT_DIR,
-            templates: [
-                'modules/account/password/password-strength-bar.scss'
-            ]
-        },
-        {
-            condition: generator => !generator.useSass,
-            path: REACT_DIR,
-            templates: [
-                'modules/account/password/password-strength-bar.css'
-            ]
-        }
     ],
     adminModule: [
         {
@@ -270,6 +253,7 @@ const files = {
                 { file: 'modules/administration/logs/logs.tsx', method: 'processJsx' },
                 { file: 'modules/administration/metrics/metrics.tsx', method: 'processJsx' },
                 { file: 'modules/administration/metrics/metrics-modal.tsx', method: 'processJsx' },
+                'modules/administration/administration.reducer.ts'
             ]
         },
         // {
@@ -287,7 +271,8 @@ const files = {
                 { file: 'modules/administration/user-management/user-management.tsx', method: 'processJsx' },
                 { file: 'modules/administration/user-management/user-management-dialog.tsx', method: 'processJsx' },
                 { file: 'modules/administration/user-management/user-management-detail.tsx', method: 'processJsx' },
-                { file: 'modules/administration/user-management/user-management-delete-dialog.tsx', method: 'processJsx' }
+                { file: 'modules/administration/user-management/user-management-delete-dialog.tsx', method: 'processJsx' },
+                'modules/administration/user-management/user-management.reducer.ts'
             ]
         },
         {
@@ -305,11 +290,13 @@ const files = {
                 // layouts
                 'shared/layout/footer/footer.tsx',
                 'shared/layout/header/header.tsx',
+                { file: 'shared/layout/password/password-strength-bar.tsx', method: 'processJsx' },
                 // util
                 'shared/util/date-utils.ts',
-                'shared/util/pagination.constants.ts'
+                'shared/util/pagination.constants.ts',
                 // components
                 // model
+                'shared/model/user.model.ts'
             ]
         },
         {
@@ -317,7 +304,8 @@ const files = {
             path: REACT_DIR,
             templates: [
                 'shared/layout/header/header.scss',
-                'shared/layout/footer/footer.scss'
+                'shared/layout/footer/footer.scss',
+                'shared/layout/password/password-strength-bar.scss'
             ]
         },
         {
@@ -325,7 +313,8 @@ const files = {
             path: REACT_DIR,
             templates: [
                 'shared/layout/header/header.css',
-                'shared/layout/footer/footer.css'
+                'shared/layout/footer/footer.css',
+                'shared/layout/password/password-strength-bar.css'
             ]
         },
     // {
@@ -390,17 +379,18 @@ const files = {
                 'spec/app/utils.ts',
                 'spec/app/config/notification-middleware.spec.ts',
                 'spec/app/shared/layout/header.spec.tsx',
-                'spec/app/reducers/register.spec.ts',
-                'spec/app/reducers/activate.spec.ts',
-                'spec/app/reducers/account.spec.ts',
-                'spec/app/reducers/authentication.spec.ts',
-                'spec/app/reducers/user-management.spec.ts',
+                'spec/app/shared/reducers/authentication.spec.ts',
+                'spec/app/modules/account/register/register.spec.tsx',
+                'spec/app/modules/account/register/register.reducer.spec.ts',
+                'spec/app/modules/account/activate/activate.reducer.spec.ts',
+                'spec/app/modules/account/password/password.reducer.spec.ts',
+                'spec/app/modules/account/settings/settings.reducer.spec.ts',
+                'spec/app/modules/administration/user-management/user-management.reducer.spec.ts',
                 // 'spec/app/account/activate/_activate.component.spec.js',
                 // 'spec/app/account/password/_password.component.spec.js',
                 // 'spec/app/account/password/_password-strength-bar.component.spec.js',
                 // 'spec/app/account/password-reset/init/_password-reset-init.component.spec.js',
                 // 'spec/app/account/password-reset/finish/_password-reset-finish.component.spec.js',
-                // 'spec/app/account/register/component.spec.js',
                 // 'spec/app/account/settings/_settings.component.spec.js',
                 // 'spec/app/admin/health/_health.component.spec.js',
                 // 'spec/app/admin/audits/_audits.component.spec.js',
diff --git a/generators/client/templates/angular/tsconfig.json.ejs b/generators/client/templates/angular/tsconfig.json.ejs
index eb86a23cc3..2b5467264f 100644
--- a/generators/client/templates/angular/tsconfig.json.ejs
+++ b/generators/client/templates/angular/tsconfig.json.ejs
@@ -35,7 +35,7 @@
         ],
         "baseUrl": "./",
         "paths": {
-            "app/*": ["src/main/webapp/app/*"]
+            "app/*": ["<%= MAIN_SRC_DIR %>app/*"]
         },
         "importHelpers": true
     },
diff --git a/generators/client/templates/angular/webpack/webpack.common.js.ejs b/generators/client/templates/angular/webpack/webpack.common.js.ejs
index 1b2bae2a3d..040bbe088a 100644
--- a/generators/client/templates/angular/webpack/webpack.common.js.ejs
+++ b/generators/client/templates/angular/webpack/webpack.common.js.ejs
@@ -31,7 +31,7 @@ module.exports = (options) => ({
         extensions: ['.ts', '.js'],
         modules: ['node_modules'],
         alias: {
-            app: utils.root('src/main/webapp/app/'),
+            app: utils.root('<%= MAIN_SRC_DIR %>app/'),
             ...rxPaths()
         }
     },
diff --git a/generators/client/templates/react/.editorconfig b/generators/client/templates/react/.editorconfig
index 06e81b10f3..77bb5c4138 100644
--- a/generators/client/templates/react/.editorconfig
+++ b/generators/client/templates/react/.editorconfig
@@ -17,7 +17,7 @@ charset = utf-8
 trim_trailing_whitespace = true
 insert_final_newline = true
 
-[*.{ts,tsx,js,jsx,json,scss,sql}]
+[*.{ts,tsx,js,jsx,json,scss,sql,ejs}]
 indent_style = space
 indent_size = 2
 
diff --git a/generators/client/templates/react/package.json.ejs b/generators/client/templates/react/package.json.ejs
index 4c3808276f..1238de1bb5 100644
--- a/generators/client/templates/react/package.json.ejs
+++ b/generators/client/templates/react/package.json.ejs
@@ -27,32 +27,32 @@ limitations under the License.
   ],
   "dependencies": {
     "availity-reactstrap-validation": "2.0.0-alpha.1",
-    "axios": "0.17.0",
-    "bootstrap": "4.0.0-beta.2",
+    "axios": "0.18.0",
+    "bootstrap": "4.0.0",
     "loaders.css": "0.1.2",
-    "lodash": "4.17.4",
-    "moment": "2.19.1",
-    "react": "16.0.0",
+    "lodash": "4.17.5",
+    "moment": "2.21.0",
+    "react": "16.2.0",
     "react-addons-css-transition-group": "16.0.0-alpha.3",
     "react-addons-transition-group": "16.0.0-alpha.3",
-    "react-dom": "16.0.0",
+    "react-dom": "16.2.0",
     "react-hot-loader": "3.1.1",
     "react-icons": "2.2.7",
-    "react-jhipster": "0.3.0",
-    "react-redux": "5.0.6",
+    "react-jhipster": "0.4.4",
+    "react-redux": "5.0.7",
     "react-redux-loading-bar": "2.9.3",
     "react-router-dom": "4.2.2",
-    "react-router-modal": "1.2.0",
+    "react-router-modal": "1.3.2",
     "react-transition-group": "2.2.1",
-    "reactstrap": "5.0.0-alpha.4",
+    "reactstrap": "5.0.0-beta.2",
     "redux": "3.7.2",
-    "redux-devtools": "3.4.0",
-    "redux-devtools-dock-monitor": "1.1.2",
-    "redux-devtools-log-monitor": "1.3.0",
+    "redux-devtools": "3.4.1",
+    "redux-devtools-dock-monitor": "1.1.3",
+    "redux-devtools-log-monitor": "1.4.0",
     "redux-promise-middleware": "4.4.2",
     "redux-thunk": "2.2.0",
     "tslib": "1.9.0",
-    "uuid": "3.1.0"
+    "uuid": "3.2.1"
   },
   "devDependencies": {
     "@types/chai": "4.0.4",
diff --git a/generators/client/templates/react/src/main/webapp/app/app.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/app.tsx.ejs
index 5ee591ff31..fed687985a 100644
--- a/generators/client/templates/react/src/main/webapp/app/app.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/app.tsx.ejs
@@ -6,13 +6,14 @@ import { Card } from 'reactstrap';
 import { HashRouter as Router } from 'react-router-dom';
 import { ModalContainer } from 'react-router-modal';
 
-import { getSession, logout } from './reducers/authentication';
+import { getSession, logout } from './shared/reducers/authentication';
 <%_ if (enableTranslation) { _%>
-import { setLocale } from './reducers/locale';
+import { setLocale } from './shared/reducers/locale';
 <%_ } _%>
 import Header from './shared/layout/header/header';
 import Footer from './shared/layout/footer/footer';
 import AppRoutes from './routes';
+
 export interface IAppProps {
   location: any;
   isAuthenticated?: boolean;
@@ -28,7 +29,7 @@ export interface IAppProps {
   routes: any;
 }
 
-export class App extends React.Component<IAppProps, {}> {
+export class App extends React.Component<IAppProps> {
   componentDidMount() {
     this.props.getSession();
   }
@@ -44,10 +45,11 @@ export class App extends React.Component<IAppProps, {}> {
         <div className="app-container" style={{ paddingTop }}>
           <Header
             isAuthenticated={this.props.isAuthenticated}
-          <% if (enableTranslation) { %>
+          <%_ if (enableTranslation) { _%>
             currentLocale={this.props.currentLocale}
             onLocaleChange={this.props.setLocale}
-          <% } %>/>
+          <%_ } _%>
+          />
           <div className="container-fluid view-container" id="app-view-container">
             <Card className="jh-card">
               <AppRoutes/>
diff --git a/generators/client/templates/react/src/main/webapp/app/config/store.ts.ejs b/generators/client/templates/react/src/main/webapp/app/config/store.ts.ejs
index 0185c9bee4..3ebeb2998e 100644
--- a/generators/client/templates/react/src/main/webapp/app/config/store.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/config/store.ts.ejs
@@ -1,7 +1,7 @@
 import { createStore, applyMiddleware, compose } from 'redux';
 import promiseMiddleware from 'redux-promise-middleware';
 import thunkMiddleware from 'redux-thunk';
-import reducer from '../reducers';
+import reducer from 'app/shared/reducers';
 import DevTools from './devtools';
 import errorMiddleware from './error-middleware';
 import notificationMiddleware from './notification-middleware';
@@ -20,18 +20,7 @@ const composedMiddlewares = middlewares => process.env.NODE_ENV === 'development
   compose(applyMiddleware(...defaultMiddlewares, ...middlewares), DevTools.instrument()) :
   compose(applyMiddleware(...defaultMiddlewares, ...middlewares));
 
-const initialize = (initialState = {}, middlewares = []) => {
-  const store = createStore(reducer, initialState, composedMiddlewares(middlewares));
-
-  // Enable Webpack hot module replacement for reducers
-  if (module.hot) {
-    // TODO : see if reducers can be moved to feature modules and still get HMR working
-    module.hot.accept('../reducers', () => {
-      const nextReducer = require('../reducers').default;
-      store.replaceReducer(nextReducer);
-    });
-  }
-  return store;
-};
+const initialize = (initialState = {}, middlewares = []) =>
+    createStore(reducer, initialState, composedMiddlewares(middlewares));
 
 export default initialize;
diff --git a/generators/client/templates/react/src/main/webapp/app/config/translation.ts.ejs b/generators/client/templates/react/src/main/webapp/app/config/translation.ts.ejs
index 9814049281..8d8141ff63 100644
--- a/generators/client/templates/react/src/main/webapp/app/config/translation.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/config/translation.ts.ejs
@@ -2,7 +2,7 @@
 import { TranslatorContext, Storage } from 'react-jhipster';
 import { merge } from 'lodash';
 
-import { setLocale } from '../reducers/locale';
+import { setLocale } from 'app/shared/reducers/locale';
 
 const mergeTranslations = requireContext => requireContext.keys().reduce(
   (merged, key) => merge({ ...merged }, { ...requireContext(key) }),
diff --git a/generators/client/templates/react/src/main/webapp/app/index.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/index.tsx.ejs
index bac55b3b84..fcf711306e 100644
--- a/generators/client/templates/react/src/main/webapp/app/index.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/index.tsx.ejs
@@ -10,7 +10,7 @@ import initStore from './config/store';
 import { registerLocales } from './config/translation';
 <%_ } _%>
 import setupAxiosInterceptors from './config/axios-interceptor';
-import { clearAuthentication } from './reducers/authentication';
+import { clearAuthentication } from './shared/reducers/authentication';
 import AppComponent from './app';
 
 const devTools = process.env.NODE_ENV === 'development' ? <DevTools /> : null;
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/activate.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.reducer.ts.ejs
similarity index 92%
rename from generators/client/templates/react/src/main/webapp/app/reducers/activate.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.reducer.ts.ejs
index 80b576e0b6..ef872eed2b 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/activate.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.reducer.ts.ejs
@@ -1,6 +1,6 @@
 import axios from 'axios';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
   ACTIVATE_ACCOUNT: 'activate/ACTIVATE_ACCOUNT',
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.tsx.ejs
index f9edb6075d..0131eb0ec9 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/activate/activate.tsx.ejs
@@ -1,11 +1,10 @@
 import * as React from 'react';
 import { connect } from 'react-redux';
-
 import { Link } from 'react-router-dom';
 import { Row, Col, Alert } from 'reactstrap';
 import { Translate } from 'react-jhipster';
 
-import { activateAction, reset } from '../../../reducers/activate';
+import { activateAction, reset } from './activate.reducer';
 
 const successAlert = (
   <Alert color="success">
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/finish/password-reset-finish.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/finish/password-reset-finish.tsx.ejs
index b6bbc257b1..6fb2c16ddd 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/finish/password-reset-finish.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/finish/password-reset-finish.tsx.ejs
@@ -1,13 +1,12 @@
 import * as React from 'react';
 import { connect } from 'react-redux';
-
 import { Alert, Col, Row, Button } from 'reactstrap';
 import { AvForm, AvField } from 'availity-reactstrap-validation';
 import { Translate, translate } from 'react-jhipster';
 import { Link } from 'react-router-dom';
 
-import { handlePasswordResetFinish, reset } from '../../../../reducers/password-reset';
-import PasswordStrengthBar from '../../password/password-strength-bar';
+import { handlePasswordResetFinish, reset } from '../password-reset.reducer';
+import PasswordStrengthBar from 'app/shared/layout/password/password-strength-bar';
 
 const actionRequiredAlert = (
   <Alert color="warning" >
@@ -46,7 +45,7 @@ export interface IPasswordResetFinishState {
   key: string;
 }
 
-export class PasswordResetFinishPage extends React.Component<IPasswordResetFinishProps> {
+export class PasswordResetFinishPage extends React.Component<IPasswordResetFinishProps, IPasswordResetFinishState> {
   state: IPasswordResetFinishState = {
     password: '',
     key: this.props.match.params.key
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/init/password-reset-init.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/init/password-reset-init.tsx.ejs
index 796de31b46..45be6b3527 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/init/password-reset-init.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/init/password-reset-init.tsx.ejs
@@ -1,10 +1,10 @@
 import * as React from 'react';
 import { Translate, translate } from 'react-jhipster';
 import { connect } from 'react-redux';
-
 import { AvForm, AvField } from 'availity-reactstrap-validation';
 import { Button, Alert } from 'reactstrap';
-import { handlePasswordResetInit, reset } from '../../../../reducers/password-reset';
+
+import { handlePasswordResetInit, reset } from '../password-reset.reducer';
 
 export interface IPasswordResetInitProps {
   handlePasswordResetInit: Function;
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/password-reset.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/password-reset.reducer.ts.ejs
similarity index 95%
rename from generators/client/templates/react/src/main/webapp/app/reducers/password-reset.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/password-reset.reducer.ts.ejs
index 21f3592a09..bc19d9938f 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/password-reset.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/password-reset/password-reset.reducer.ts.ejs
@@ -1,6 +1,6 @@
 import axios from 'axios';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
   RESET_PASSWORD_INIT: 'passwordReset/RESET_PASSWORD_INIT',
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/account.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.reducer.ts.ejs
similarity index 61%
rename from generators/client/templates/react/src/main/webapp/app/reducers/account.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/account/password/password.reducer.ts.ejs
index 4321e60eed..d5f78de11b 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/account.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.reducer.ts.ejs
@@ -1,9 +1,8 @@
 import axios from 'axios';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
-  UPDATE_ACCOUNT: 'account/UPDATE_ACCOUNT',
   UPDATE_PASSWORD: 'account/UPDATE_PASSWORD',
   RESET: 'account/RESET'
 };
@@ -11,7 +10,6 @@ export const ACTION_TYPES = {
 const initialState = {
   loading: false,
   errorMessage: null,
-  account: {},
   updateSuccess: false,
   updateFailure: false
 };
@@ -19,13 +17,6 @@ const initialState = {
 // Reducer
 export default (state = initialState, action) => {
   switch (action.type) {
-    case REQUEST(ACTION_TYPES.UPDATE_ACCOUNT):
-      return {
-        ...state,
-        errorMessage: null,
-        updateSuccess: false,
-        loading: true
-      };
     case REQUEST(ACTION_TYPES.UPDATE_PASSWORD):
       return {
         ...initialState,
@@ -33,21 +24,6 @@ export default (state = initialState, action) => {
         updateSuccess: false,
         loading: true
       };
-    case FAILURE(ACTION_TYPES.UPDATE_ACCOUNT):
-      return {
-        ...state,
-        loading: false,
-        updateSuccess: false,
-        updateFailure: true
-      };
-    case SUCCESS(ACTION_TYPES.UPDATE_ACCOUNT):
-      return {
-        ...state,
-        loading: false,
-        updateSuccess: true,
-        updateFailure: false,
-        account: action.payload.data
-      };
     case FAILURE(ACTION_TYPES.UPDATE_PASSWORD):
       return {
         ...initialState,
@@ -79,11 +55,6 @@ export const savePassword = (currentPassword, newPassword) => ({
   payload: axios.post(`${apiUrl}/change-password`, { currentPassword, newPassword })
 });
 
-export const saveAccountSettings = account => ({
-  type: ACTION_TYPES.UPDATE_ACCOUNT,
-  payload: axios.post(apiUrl, account)
-});
-
 export const reset = () => ({
   type: ACTION_TYPES.RESET
 });
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.tsx.ejs
index 3f1a3ecbf0..b64b0857a5 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.tsx.ejs
@@ -1,15 +1,12 @@
-/* eslint-disable */ // TODO Fix when page is completed
 import * as React from 'react';
 import { Translate, translate } from 'react-jhipster';
 import { connect } from 'react-redux';
-
 import { AvForm, AvField } from 'availity-reactstrap-validation';
 import { Row, Col, Button, Alert } from 'reactstrap';
 
-import { getSession } from '../../../reducers/authentication';
-import { savePassword, reset } from '../../../reducers/account';
-
-import PasswordStrengthBar from './password-strength-bar';
+import { getSession } from 'app/shared/reducers/authentication';
+import PasswordStrengthBar from 'app/shared/layout/password/password-strength-bar';
+import { savePassword, reset } from './password.reducer';
 
 export interface IUserSettingsProps {
   account: any;
@@ -24,7 +21,7 @@ export interface IUserSettingsState {
   password: string;
 }
 
-export class SettingsPage extends React.Component<IUserSettingsProps> {
+export class SettingsPage extends React.Component<IUserSettingsProps, IUserSettingsState> {
   state: IUserSettingsState = {
     password: ''
   };
@@ -124,9 +121,9 @@ export class SettingsPage extends React.Component<IUserSettingsProps> {
   }
 }
 
-const mapStateToProps = ({ authentication, account }) => ({
-  updateSuccess: account.updateSuccess,
-  updateFailure: account.updateFailure,
+const mapStateToProps = ({ authentication, password }) => ({
+  updateSuccess: password.updateSuccess,
+  updateFailure: password.updateFailure,
   account: authentication.account,
   isAuthenticated: authentication.isAuthenticated
 });
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/register.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.reducer.ts.ejs
similarity index 93%
rename from generators/client/templates/react/src/main/webapp/app/reducers/register.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/account/register/register.reducer.ts.ejs
index 8dd910f3f1..e83c1a5315 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/register.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.reducer.ts.ejs
@@ -1,6 +1,6 @@
 import axios from 'axios';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
   CREATE_ACCOUNT: 'register/CREATE_ACCOUNT',
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.tsx.ejs
index 0b5b316917..fe06d9bd88 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/register/register.tsx.ejs
@@ -1,12 +1,11 @@
 import * as React from 'react';
 import { Translate, translate } from 'react-jhipster';
 import { connect } from 'react-redux';
-
 import { AvForm, AvField } from 'availity-reactstrap-validation';
 import { Row, Col, Alert, Button } from 'reactstrap';
-import PasswordStrengthBar from '../password/password-strength-bar';
 
-import { handleRegister, reset } from '../../../reducers/register';
+import PasswordStrengthBar from 'app/shared/layout/password/password-strength-bar';
+import { handleRegister, reset } from './register.reducer';
 
 export const mainErrorMessages = {
   failed: (
@@ -39,7 +38,7 @@ export interface IRegisterState {
   password: string;
 }
 
-export class RegisterPage extends React.Component<IRegisterProps> {
+export class RegisterPage extends React.Component<IRegisterProps, IRegisterState> {
   state: IRegisterState = {
     password: ''
   };
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.reducer.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.reducer.ts.ejs
new file mode 100644
index 0000000000..94f99e14c9
--- /dev/null
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.reducer.ts.ejs
@@ -0,0 +1,64 @@
+import axios from 'axios';
+
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
+import { getSession } from 'app/shared/reducers/authentication';
+
+export const ACTION_TYPES = {
+  UPDATE_ACCOUNT: 'account/UPDATE_ACCOUNT',
+  RESET: 'account/RESET'
+};
+
+const initialState = {
+  loading: false,
+  errorMessage: null,
+  updateSuccess: false,
+  updateFailure: false
+};
+
+// Reducer
+export default (state = initialState, action) => {
+  switch (action.type) {
+    case REQUEST(ACTION_TYPES.UPDATE_ACCOUNT):
+      return {
+        ...state,
+        errorMessage: null,
+        updateSuccess: false,
+        loading: true
+      };
+    case FAILURE(ACTION_TYPES.UPDATE_ACCOUNT):
+      return {
+        ...state,
+        loading: false,
+        updateSuccess: false,
+        updateFailure: true
+      };
+    case SUCCESS(ACTION_TYPES.UPDATE_ACCOUNT):
+      return {
+        ...state,
+        loading: false,
+        updateSuccess: true,
+        updateFailure: false
+      };
+    case ACTION_TYPES.RESET:
+      return {
+        ...initialState
+      };
+    default:
+      return state;
+  }
+};
+
+// Actions
+const apiUrl = '/api/account';
+
+export const saveAccountSettings = account => async dispatch => {
+  await dispatch({
+    type: ACTION_TYPES.UPDATE_ACCOUNT,
+    payload: axios.post(apiUrl, account)
+  })
+  dispatch(getSession())
+};
+
+export const reset = () => ({
+  type: ACTION_TYPES.RESET
+});
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.tsx.ejs
index fc875e95a1..4fca911384 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/account/settings/settings.tsx.ejs
@@ -3,11 +3,12 @@ import { Button, Col, Alert, Row } from 'reactstrap';
 import { connect } from 'react-redux';
 import { Translate, translate } from 'react-jhipster';
 import { AvForm, AvField } from 'availity-reactstrap-validation';
-import { getSession } from '../../../reducers/authentication';
-import { saveAccountSettings, reset } from '../../../reducers/account';
+
 <%_ if (enableTranslation) { _%>
-  import { locales } from '../../../config/translation';
+import { locales } from 'app/config/translation';
 <%_ } _%>
+import { getSession } from 'app/shared/reducers/authentication';
+import { saveAccountSettings, reset } from './settings.reducer';
 
 const successAlert = (
   <Alert color="success" >
@@ -27,7 +28,7 @@ export interface IUserSettingsState {
   account: any;
 }
 
-export class SettingsPage extends React.Component<IUserSettingsProps> {
+export class SettingsPage extends React.Component<IUserSettingsProps, IUserSettingsState> {
   state: IUserSettingsState = {
     account: this.props.account
   };
@@ -60,9 +61,8 @@ export class SettingsPage extends React.Component<IUserSettingsProps> {
   handleValidSubmit = (event, values) => {
     const account = {
       ...this.state.account,
-      ...values<%_ if (enableTranslation) { _%>,
-      langKey: this.state.account.langKey
-      <%_ } _%>
+      ...values<% if (enableTranslation) { %>,
+      langKey: this.state.account.langKey<% } %>
     };
 
     this.props.saveAccountSettings(account);
@@ -152,11 +152,11 @@ export class SettingsPage extends React.Component<IUserSettingsProps> {
   }
 }
 
-const mapStateToProps = ({ authentication, account }) => ({
+const mapStateToProps = ({ authentication, settings }) => ({
   account: authentication.account,
   isAuthenticated: authentication.isAuthenticated,
-  updateSuccess: account.updateSuccess,
-  updateFailure: account.updateFailure
+  updateSuccess: settings.updateSuccess,
+  updateFailure: settings.updateFailure
 });
 
 const mapDispatchToProps = { getSession, saveAccountSettings, reset };
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/administration.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/administration.reducer.ts.ejs
similarity index 97%
rename from generators/client/templates/react/src/main/webapp/app/reducers/administration.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/administration/administration.reducer.ts.ejs
index 7cb63f51e3..eca4a04b8a 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/administration.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/administration.reducer.ts.ejs
@@ -1,6 +1,6 @@
 import axios from 'axios';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
   FETCH_GATEWAY_ROUTE: 'administration/FETCH_GATEWAY_ROUTE',
@@ -156,7 +156,7 @@ export const systemMetrics = () => ({
 
 export const systemThreadDump = () => ({
   type: ACTION_TYPES.FETCH_THREAD_DUMP,
-  payload: axios.get('/management/dump')
+  payload: axios.get('/management/threaddump')
 });
 
 export const getLoggers = () => ({
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/audits/audits.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/audits/audits.tsx.ejs
index e5d613dff3..3063055226 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/audits/audits.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/audits/audits.tsx.ejs
@@ -7,13 +7,13 @@ import {
   JhiPagination,
   getPaginationItemsNumber,
   getSortState,
-  IPaginationState
+  IPaginationBaseState
 } from 'react-jhipster';
 import { FaSort } from 'react-icons/lib/fa';
 
-import { getAudits } from '../../../reducers/administration';
-import { APP_TIMESTAMP_FORMAT } from '../../../config/constants';
-import { ITEMS_PER_PAGE } from '../../../shared/util/pagination.constants';
+import { APP_TIMESTAMP_FORMAT } from 'app/config/constants';
+import { ITEMS_PER_PAGE } from 'app/shared/util/pagination.constants';
+import { getAudits } from '../administration.reducer';
 
 export interface IAuditsPageProps {
   isFetching?: boolean;
@@ -26,16 +26,34 @@ export interface IAuditsPageProps {
   onChangeToDate: any;
 }
 
-export class AuditsPage extends React.Component<IAuditsPageProps, IPaginationState> {
+export interface IAuditsPageState extends IPaginationBaseState {
+  fromDate: string;
+  toDate: string;
+}
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      ...getSortState(props.location, ITEMS_PER_PAGE),
-      fromDate: this.previousMonth(),
-      toDate: this.today()
-    };
-  }
+const previousMonth = (): string => {
+  const now: Date = new Date();
+  const fromDate =
+    now.getMonth() === 0
+      ? new Date(now.getFullYear() - 1, 11, now.getDate())
+      : new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
+  return fromDate.toISOString().slice(0, 10);
+};
+
+const today = (): string => {
+  // Today + 1 day - needed if the current day must be included
+  const day: Date = new Date();
+  day.setDate(day.getDate() + 1);
+  const toDate = new Date(day.getFullYear(), day.getMonth(), day.getDate());
+  return toDate.toISOString().slice(0, 10);
+};
+
+export class AuditsPage extends React.Component<IAuditsPageProps, IAuditsPageState> {
+  state: IAuditsPageState = {
+    ...getSortState(this.props.location, ITEMS_PER_PAGE),
+    fromDate: previousMonth(),
+    toDate: today()
+  };
 
   componentDidMount() {
     this.getAudits();
@@ -52,22 +70,6 @@ export class AuditsPage extends React.Component<IAuditsPageProps, IPaginationSta
     }, () => this.getAudits());
   }
 
-  previousMonth = (): string => {
-    const now: Date = new Date();
-    const fromDate = now.getMonth() === 0
-      ? new Date(now.getFullYear() - 1, 11, now.getDate())
-      : new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
-    return fromDate.toISOString().slice(0, 10);
-  }
-
-  today = (): string => {
-    // Today + 1 day - needed if the current day must be included
-    const today: Date = new Date();
-    today.setDate(today.getDate() + 1);
-    const toDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
-    return toDate.toISOString().slice(0, 10);
-  }
-
   sort = prop => () => {
     this.setState({
       order: this.state.order === 'asc' ? 'desc' : 'asc',
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/configuration/configuration.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/configuration/configuration.tsx.ejs
index bccae6324f..d12f92cf4a 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/configuration/configuration.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/configuration/configuration.tsx.ejs
@@ -4,7 +4,7 @@ import { Table, Input } from 'reactstrap';
 import { Translate } from 'react-jhipster';
 import { sortBy, reverse } from 'lodash';
 
-import { getConfigurations, getEnv } from '../../../reducers/administration';
+import { getConfigurations, getEnv } from '../administration.reducer';
 
 export interface IConfigurationPageProps {
   isFetching?: boolean;
@@ -20,15 +20,11 @@ export interface IConfigurationPageState {
 }
 
 export class ConfigurationPage extends React.Component<IConfigurationPageProps, IConfigurationPageState> {
-
-  constructor(props) {
-    super(props);
-    this.state = {
-      filter: '',
-      reversePrefix: false,
-      reverseProperties: false
-    };
-  }
+  state: IConfigurationPageState = {
+    filter: '',
+    reversePrefix: false,
+    reverseProperties: false
+  };
 
   componentDidMount() {
     this.props.getConfigurations();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/gateway/gateway.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/gateway/gateway.tsx.ejs
index b08bd63d77..2b7e86568d 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/gateway/gateway.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/gateway/gateway.tsx.ejs
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
 import { Translate, ICrudGetAction } from 'react-jhipster';
 import { FaRefresh } from 'react-icons/lib/fa';
 
-import { gatewayRoutes } from '../../../reducers/administration';
+import { gatewayRoutes } from '../administration.reducer';
 
 export interface IGatewayPageProps {
   gatewayRoutes: ICrudGetAction;
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/health/health.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/health/health.tsx.ejs
index 64289e955e..8f2211b277 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/health/health.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/health/health.tsx.ejs
@@ -4,8 +4,8 @@ import { Translate } from 'react-jhipster';
 import { Table } from 'reactstrap';
 import { FaEye, FaRefresh } from 'react-icons/lib/fa';
 
+import { systemHealth } from '../administration.reducer';
 import HealthModal from './health-modal';
-import { systemHealth } from '../../../reducers/administration';
 
 export interface IHealthPageProps {
   isFetching?: boolean;
@@ -14,15 +14,16 @@ export interface IHealthPageProps {
   systemHealthInfo: any;
 }
 
-export class HealthPage extends React.Component<IHealthPageProps, any> {
+export interface IHealthPageState {
+  healthObject: any,
+  showModal: boolean
+}
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      healthObject: {},
-      showModal: false
-    };
-  }
+export class HealthPage extends React.Component<IHealthPageProps, IHealthPageState> {
+  state: IHealthPageState = {
+    healthObject: {},
+    showModal: false
+  };
 
   componentDidMount() {
     this.props.systemHealth();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/logs/logs.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/logs/logs.tsx.ejs
index 2f9f101b1e..8c59ef69ea 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/logs/logs.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/logs/logs.tsx.ejs
@@ -2,7 +2,7 @@ import * as React from 'react';
 import { connect } from 'react-redux';
 import { Translate } from 'react-jhipster';
 
-import { getLoggers, changeLogLevel } from '../../../reducers/administration';
+import { getLoggers, changeLogLevel } from '../administration.reducer';
 
 export interface ILogsPageProps {
   isFetching?: boolean;
@@ -11,14 +11,15 @@ export interface ILogsPageProps {
   logs: any;
 }
 
-export class LogsPage extends React.Component<ILogsPageProps, { filter: string }> {
+export interface ILogsPageState {
+  filter: string
+}
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      filter: ''
-    };
-  }
+export class LogsPage extends React.Component<ILogsPageProps, ILogsPageState> {
+
+  state: ILogsPageState = {
+    filter: ''
+  };
 
   componentDidMount() {
     this.props.getLoggers();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics-modal.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics-modal.tsx.ejs
index 9fb499b778..15c7967bc4 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics-modal.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics-modal.tsx.ejs
@@ -8,7 +8,7 @@ const MetricsModal = ({ handleClose, showModal, threadDump }) => (
   >
     <ModalHeader toggle={handleClose}>Thread Dump Info</ModalHeader>
     <ModalBody>
-      {threadDump ? threadDump.map((threadDumpInfo, i) => (
+      {threadDump && threadDump.threads ? threadDump.threads.map((threadDumpInfo, i) => (
         <div key={`dump-${i}`}>
           <h5>{threadDumpInfo.threadState} {threadDumpInfo.threadName} (ID {threadDumpInfo.threadId})</h5>
           <div className="row" >
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics.tsx.ejs
index 18deea6874..3581639a4b 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics.tsx.ejs
@@ -4,9 +4,9 @@ import { Table, Progress } from 'reactstrap';
 import { Translate, TextFormat } from 'react-jhipster';
 import { FaEye, FaRefresh } from 'react-icons/lib/fa';
 
+import { APP_WHOLE_NUMBER_FORMAT, APP_TWO_DIGITS_AFTER_POINT_NUMBER_FORMAT } from 'app/config/constants';
+import { systemMetrics, systemThreadDump } from '../administration.reducer';
 import MetricsModal from './metrics-modal';
-import { systemMetrics, systemThreadDump } from '../../../reducers/administration';
-import { APP_WHOLE_NUMBER_FORMAT, APP_TWO_DIGITS_AFTER_POINT_NUMBER_FORMAT } from '../../../config/constants';
 
 export interface IMetricsPageProps {
   isFetching?: boolean;
@@ -16,14 +16,14 @@ export interface IMetricsPageProps {
   threadDump: any;
 }
 
-export class MetricsPage extends React.Component<any, any> {
+export interface IMetricsPageState {
+  showModal: boolean;
+}
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      showModal: false
-    };
-  }
+export class MetricsPage extends React.Component<any, IMetricsPageState> {
+  state: IMetricsPageState = {
+    showModal: false
+  };
 
   componentDidMount() {
     this.props.systemMetrics();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-delete-dialog.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-delete-dialog.tsx.ejs
index 229069cbcc..c31c2600a2 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-delete-dialog.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-delete-dialog.tsx.ejs
@@ -4,7 +4,7 @@ import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
 import { Translate, ICrudGetAction, ICrudDeleteAction } from 'react-jhipster';
 import { FaBan, FaTrash } from 'react-icons/lib/fa';
 
-import { getUser, deleteUser } from '../../../reducers/user-management';
+import { getUser, deleteUser } from './user-management.reducer';
 
 export interface IUserManagementDeleteDialogProps {
   getUser: ICrudGetAction;
@@ -19,12 +19,9 @@ export interface IUserManagementDeleteDialogState {
 }
 export class UserManagementDeleteDialog extends React.Component<IUserManagementDeleteDialogProps, IUserManagementDeleteDialogState> {
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      showModal: true
-    };
-  }
+  state: IUserManagementDeleteDialogState = {
+    showModal: true
+  };
 
   componentDidMount() {
     this.props.getUser(this.props.match.params.login);
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-detail.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-detail.tsx.ejs
index 0d83975690..63287de1b2 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-detail.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-detail.tsx.ejs
@@ -5,16 +5,16 @@ import { Button } from 'reactstrap';
 import { Translate, ICrudGetAction, TextFormat } from 'react-jhipster';
 import { FaArrowLeft } from 'react-icons/lib/fa';
 
-import { getUser } from '../../../reducers/user-management';
-import { APP_DATE_FORMAT } from '../../../config/constants';
+import { APP_DATE_FORMAT } from 'app/config/constants';
+import { getUser } from './user-management.reducer';
 
 export interface IUserManagementDetailProps {
   getUser: ICrudGetAction;
   user: any;
   match: any;
 }
-export class UserManagementDetail extends React.Component<IUserManagementDetailProps, undefined> {
 
+export class UserManagementDetail extends React.Component<IUserManagementDetailProps> {
   componentDidMount() {
     this.props.getUser(this.props.match.params.login);
   }
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-dialog.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-dialog.tsx.ejs
index ee66150abf..d4dbb89ca2 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-dialog.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management-dialog.tsx.ejs
@@ -2,17 +2,17 @@ import * as React from 'react';
 import { connect } from 'react-redux';
 import { Modal, ModalHeader, ModalBody, ModalFooter, Button, Label } from 'reactstrap';
 import { AvForm, AvGroup, AvInput, AvFeedback } from 'availity-reactstrap-validation';
-import { Translate, ICrudGetAction, ICrudPutAction } from 'react-jhipster';
+import { Translate, ICrudGetAction, ICrudGetAllAction, ICrudPutAction } from 'react-jhipster';
 import { FaBan, FaFloppyO } from 'react-icons/lib/fa';
 
-import { getUser, getRoles, updateUser, createUser } from '../../../reducers/user-management';
 <%_ if (enableTranslation) { _%>
-import { locales } from '../../../config/translation';
+import { locales } from 'app/config/translation';
 <%_ } _%>
+import { getUser, getRoles, updateUser, createUser } from './user-management.reducer';
 
 export interface IUserManagementDialogProps {
   getUser: ICrudGetAction;
-  getRoles: ICrudGetAction;
+  getRoles: ICrudGetAllAction;
   updateUser: ICrudPutAction;
   createUser: ICrudPutAction;
   loading: boolean;
@@ -30,13 +30,10 @@ export interface IUserManagementDialogState {
 
 export class UserManagementDialog extends React.Component<IUserManagementDialogProps, IUserManagementDialogState> {
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      showModal: true,
-      isNew: !this.props.match.params || !this.props.match.params.login
-    };
-  }
+  state: IUserManagementDialogState = {
+    showModal: true,
+    isNew: !this.props.match.params || !this.props.match.params.login
+  };
 
   componentDidMount() {
     !this.state.isNew && this.props.getUser(this.props.match.params.login);
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/user-management.ts.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.reducer.ts.ejs
similarity index 93%
rename from generators/client/templates/react/src/main/webapp/app/reducers/user-management.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.reducer.ts.ejs
index 221dba8d89..8571a7e5ea 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/user-management.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.reducer.ts.ejs
@@ -1,8 +1,8 @@
 import axios from 'axios';
-import { ICrudGetAction, ICrudPutAction, ICrudDeleteAction } from 'react-jhipster';
+import { ICrudGetAction, ICrudGetAllAction, ICrudPutAction, ICrudDeleteAction } from 'react-jhipster';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
-import { messages } from '../config/constants';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
+import { messages } from 'app/config/constants';
 
 export const ACTION_TYPES = {
   FETCH_ROLES: 'userManagement/FETCH_ROLES',
@@ -102,7 +102,7 @@ export default (state = initialState, action) => {
 
 const apiUrl = '/api/users';
 // Actions
-export const getUsers: ICrudGetAction = (page, size, sort) => {
+export const getUsers: ICrudGetAllAction = (page, size, sort) => {
   const requestUrl = `${apiUrl}${sort ? `?page=${page}&size=${size}&sort=${sort}` : ''}`;
   return {
     type: ACTION_TYPES.FETCH_USERS,
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.tsx.ejs
index ee3753caac..5dd9f7ea03 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.tsx.ejs
@@ -22,21 +22,21 @@ import { Link } from 'react-router-dom';
 import { Button } from 'reactstrap';
 import {
   Translate,
-  ICrudGetAction,
+  ICrudGetAllAction,
   TextFormat,
   JhiPagination,
   getPaginationItemsNumber,
   getSortState,
-  IPaginationState
+  IPaginationBaseState
 } from 'react-jhipster';
 import { FaPlus, FaEye, FaPencil, FaSort, FaTrash } from 'react-icons/lib/fa';
 
-import { getUsers } from '../../../reducers/user-management';
-import { APP_DATE_FORMAT } from '../../../config/constants';
-import { ITEMS_PER_PAGE } from '../../../shared/util/pagination.constants';
+import { APP_DATE_FORMAT } from 'app/config/constants';
+import { ITEMS_PER_PAGE } from 'app/shared/util/pagination.constants';
+import { getUsers } from './user-management.reducer';
 
 export interface IUserManagementProps {
-  getUsers: ICrudGetAction;
+  getUsers: ICrudGetAllAction;
   users: any[];
   account: any;
   match: any;
@@ -45,14 +45,10 @@ export interface IUserManagementProps {
   location: any;
 }
 
-export class UserManagement extends React.Component<IUserManagementProps, IPaginationState> {
-
-  constructor(props) {
-    super(props);
-    this.state = {
-      ...getSortState(props.location, ITEMS_PER_PAGE)
-    };
-  }
+export class UserManagement extends React.Component<IUserManagementProps, IPaginationBaseState> {
+  state: IPaginationBaseState = {
+    ...getSortState(this.props.location, ITEMS_PER_PAGE)
+  };
 
   componentDidMount() {
     this.getUsers();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/home/home.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/home/home.tsx.ejs
index bdbb9a796a..a9d87bb0ae 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/home/home.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/home/home.tsx.ejs
@@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
 import { Translate } from 'react-jhipster';
 import { connect } from 'react-redux';
 
-import { getSession } from '../../reducers/authentication';
+import { getSession } from 'app/shared/reducers/authentication';
 
 export interface IHomeProp {
   account: any;
@@ -17,12 +17,9 @@ export interface IHomeState {
 }
 
 export class Home extends React.Component<IHomeProp, IHomeState> {
-  constructor(props) {
-    super(props);
-    this.state = {
-      currentUser: props.account
-    };
-  }
+  state: IHomeState = {
+    currentUser: this.props.account
+  };
 
   componentWillMount() {
     this.props.getSession();
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/login/login-modal.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/login/login-modal.tsx.ejs
index 50c2781c25..d5acebaafe 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/login/login-modal.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/login/login-modal.tsx.ejs
@@ -11,13 +11,7 @@ export interface ILoginModalProps {
   handleClose: Function;
 }
 
-class LoginModal extends React.Component<ILoginModalProps, {}> {
-
-  constructor(props, context) {
-    super(props, context);
-    this.state = {};
-  }
-
+class LoginModal extends React.Component<ILoginModalProps> {
   handleSubmit = (event, errors, { username, password, rememberMe }) => {
     const { handleLogin } = this.props;
     handleLogin(username, password, rememberMe);
@@ -53,8 +47,8 @@ class LoginModal extends React.Component<ILoginModalProps, {}> {
                   placeholder={translate('login.form.password.placeholder')}
                   required errorMessage="Password cannot be empty!"
                 />
-                <AvGroup>
-                  <Label check inline for="rememberMe" className="form-check-label">
+                <AvGroup check>
+                  <Label check for="rememberMe" className="form-check-label">
                     <AvInput type="checkbox" name="rememberMe" /> <Translate contentKey="login.form.rememberme" />
                   </Label>
                 </AvGroup>
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/login/login.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/login/login.tsx.ejs
index 3e59201619..ddb4c85dd8 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/login/login.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/login/login.tsx.ejs
@@ -2,8 +2,8 @@ import * as React from 'react';
 import { connect } from 'react-redux';
 import { Redirect } from 'react-router-dom';
 
+import { login } from 'app/shared/reducers/authentication';
 import LoginModal from './login-modal';
-import { login } from '../../reducers/authentication';
 
 export interface ILoginProps {
   isAuthenticated: boolean;
@@ -20,13 +20,10 @@ export interface ILoginState {
 
 export class Login extends React.Component<ILoginProps, ILoginState> {
 
-  constructor(props) {
-    super(props);
-    this.state = {
-      showModal: props.showModal,
-      redirectToReferrer: props.isAuthenticated
-    };
-  }
+  state: ILoginState = {
+    showModal: this.props.showModal,
+    redirectToReferrer: this.props.isAuthenticated
+  };
 
   componentWillReceiveProps(nextProps: ILoginProps) {
     this.setState({
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/login/logout.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/modules/login/logout.tsx.ejs
index 8d718fa233..0c15ac487c 100644
--- a/generators/client/templates/react/src/main/webapp/app/modules/login/logout.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/modules/login/logout.tsx.ejs
@@ -2,13 +2,13 @@ import * as React from 'react';
 import { connect } from 'react-redux';
 import { Redirect } from 'react-router-dom';
 
-import { logout } from '../../reducers/authentication';
+import { logout } from 'app/shared/reducers/authentication';
 
 export interface ILogoutProps {
   logout: Function;
 }
 
-export class Logout extends React.Component<ILogoutProps, undefined> {
+export class Logout extends React.Component<ILogoutProps> {
 
   componentWillMount() {
     this.props.logout();
diff --git a/generators/client/templates/react/src/main/webapp/app/shared/layout/header/header.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/shared/layout/header/header.tsx.ejs
index e99b30d6cc..f28e70442a 100644
--- a/generators/client/templates/react/src/main/webapp/app/shared/layout/header/header.tsx.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/shared/layout/header/header.tsx.ejs
@@ -11,16 +11,19 @@ import {
   FaList, FaTasks, FaDashboard, FaBook, FaWrench, FaSignIn, FaSignOut,
   FaClockO, FaHddO,
   // tslint:disable-next-line
-  FaRoad, FaAsterisk, FaBell
+  FaRoad,
+  // tslint:disable-next-line
+  FaAsterisk,
+  // tslint:disable-next-line
+  FaBell
 } from 'react-icons/lib/fa';
-
 import { NavLink as Link } from 'react-router-dom';
 import LoadingBar from 'react-redux-loading-bar';
 
 <%_ if (enableTranslation) { _%>
-import { locales } from '../../../config/translation';
+import { locales } from 'app/config/translation';
 <%_ } _%>
-import appConfig from '../../../config/constants';
+import appConfig from 'app/config/constants';
 
 export interface IHeaderProps {
   isAuthenticated: boolean;
@@ -29,6 +32,11 @@ export interface IHeaderProps {
   onLocaleChange: Function;
 <%_ } _%>
 }
+
+export interface IHeaderState {
+  menuOpen: boolean
+}
+
 const BrandIcon = props => (
   <div {...props} className="brand-icon">
     <img
@@ -37,13 +45,10 @@ const BrandIcon = props => (
     />
   </div>
 );
-export class Header extends React.Component<IHeaderProps, { menuOpen: boolean }> {
-  constructor(props) {
-    super(props);
-    this.state = {
+export class Header extends React.Component<IHeaderProps, IHeaderState> {
+  state: IHeaderState = {
       menuOpen: false
-    };
-  }
+  };
 
   <%_ if (enableTranslation) { _%>
   handleLocaleChange = event => {
@@ -127,7 +132,7 @@ export class Header extends React.Component<IHeaderProps, { menuOpen: boolean }>
                 </NavLink>
               </NavItem>
               {isAuthenticated ? [
-                <UncontrolledDropdown nav key="entities">
+                <UncontrolledDropdown nav inNavbar key="entities">
                   <DropdownToggle nav caret className="d-flex align-items-center">
                     <FaThList />
                     <span>Entities</span>
@@ -136,7 +141,7 @@ export class Header extends React.Component<IHeaderProps, { menuOpen: boolean }>
                     {entityMenuItems}
                   </DropdownMenu>
                 </UncontrolledDropdown>,
-                <UncontrolledDropdown nav key="admin">
+                <UncontrolledDropdown nav inNavbar key="admin">
                   <DropdownToggle nav caret className="d-flex align-items-center">
                     <FaUserPlus />
                     <span>Administration</span>
@@ -148,7 +153,7 @@ export class Header extends React.Component<IHeaderProps, { menuOpen: boolean }>
               ] : null}
             <%_ if (enableTranslation) { _%>
               { locales.length > 1 ?
-                <UncontrolledDropdown nav>
+                <UncontrolledDropdown nav inNavbar>
                   <DropdownToggle nav caret className="d-flex align-items-center">
                     <FaFlag />
                     <span>{currentLocale.toUpperCase()}</span>
@@ -159,7 +164,7 @@ export class Header extends React.Component<IHeaderProps, { menuOpen: boolean }>
                 </UncontrolledDropdown> : null
               }
             <%_ } _%>
-              <UncontrolledDropdown nav>
+              <UncontrolledDropdown nav inNavbar>
                 <DropdownToggle nav caret className="d-flex align-items-center">
                   <FaUser />
                   <span>Account</span>
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.css.ejs b/generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.css.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.css.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.css.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.scss.ejs b/generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.scss.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.scss.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.scss.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.tsx.ejs b/generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.tsx.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/modules/account/password/password-strength-bar.tsx.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/layout/password/password-strength-bar.tsx.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/shared/model/user.model.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/model/user.model.ts.ejs
new file mode 100644
index 0000000000..6edbdd4ac2
--- /dev/null
+++ b/generators/client/templates/react/src/main/webapp/app/shared/model/user.model.ts.ejs
@@ -0,0 +1,66 @@
+<%#
+ Copyright 2013-2018 the original author or authors from the JHipster project.
+
+ This file is part of the JHipster project, see http://www.jhipster.tech/
+ for more information.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-%>
+
+export interface IUser {
+    id?: any;
+    login?: string;
+    firstName?: string;
+    lastName?: string;
+    email?: string;
+    activated?: boolean;
+    langKey?: string;
+    authorities?: any[];
+    createdBy?: string;
+    createdDate?: Date;
+    lastModifiedBy?: string;
+    lastModifiedDate?: Date;
+    password?: string;
+}
+
+export class User implements IUser {
+    constructor(
+        public id?: any,
+        public login?: string,
+        public firstName?: string,
+        public lastName?: string,
+        public email?: string,
+        public activated?: boolean,
+        public langKey?: string,
+        public authorities?: any[],
+        public createdBy?: string,
+        public createdDate?: Date,
+        public lastModifiedBy?: string,
+        public lastModifiedDate?: Date,
+        public password?: string
+    ) {
+        this.id = id ? id : null;
+        this.login = login ? login : null;
+        this.firstName = firstName ? firstName : null;
+        this.lastName = lastName ? lastName : null;
+        this.email = email ? email : null;
+        this.activated = activated ? activated : false;
+        this.langKey = langKey ? langKey : null;
+        this.authorities = authorities ? authorities : null;
+        this.createdBy = createdBy ? createdBy : null;
+        this.createdDate = createdDate ? createdDate : null;
+        this.lastModifiedBy = lastModifiedBy ? lastModifiedBy : null;
+        this.lastModifiedDate = lastModifiedDate ? lastModifiedDate : null;
+        this.password = password ? password : null;
+    }
+}
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/action-type.util.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/reducers/action-type.util.ts.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/reducers/action-type.util.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/reducers/action-type.util.ts.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/authentication.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/reducers/authentication.ts.ejs
similarity index 97%
rename from generators/client/templates/react/src/main/webapp/app/reducers/authentication.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/reducers/authentication.ts.ejs
index 78f7d0dbca..88334079fd 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/authentication.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/shared/reducers/authentication.ts.ejs
@@ -1,7 +1,7 @@
 import axios from 'axios';
 import { Storage } from 'react-jhipster';
 
-import { REQUEST, SUCCESS, FAILURE } from './action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
 export const ACTION_TYPES = {
   LOGIN: 'authentication/LOGIN',
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/index.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/reducers/index.ts.ejs
similarity index 52%
rename from generators/client/templates/react/src/main/webapp/app/reducers/index.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/reducers/index.ts.ejs
index d4b5982f72..0713050def 100644
--- a/generators/client/templates/react/src/main/webapp/app/reducers/index.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/shared/reducers/index.ts.ejs
@@ -6,12 +6,14 @@ import locale from './locale';
 <%_ } _%>
 import layout from './layout';
 import authentication from './authentication';
-import administration from './administration';
-import userManagement from './user-management';
-import register from './register';
-import account from './account';
-import activate from './activate';
-import passwordReset from './password-reset';
+
+import administration from 'app/modules/administration/administration.reducer';
+import userManagement from 'app/modules/administration/user-management/user-management.reducer';
+import register from 'app/modules/account/register/register.reducer';
+import activate from 'app/modules/account/activate/activate.reducer';
+import password from 'app/modules/account/password/password.reducer';
+import settings from 'app/modules/account/settings/settings.reducer';
+import passwordReset from 'app/modules/account/password-reset/password-reset.reducer';
 
 /* jhipster-needle-add-reducer-import - JHipster will add reducer here */
 
@@ -24,9 +26,10 @@ export default combineReducers({
   administration,
   userManagement,
   register,
-  account,
   activate,
   passwordReset,
+  password,
+  settings,
   /* jhipster-needle-add-reducer-combine - JHipster will add reducer here */
   loadingBar
 });
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/layout.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/reducers/layout.ts.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/reducers/layout.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/reducers/layout.ts.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/reducers/locale.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/reducers/locale.ts.ejs
similarity index 100%
rename from generators/client/templates/react/src/main/webapp/app/reducers/locale.ts.ejs
rename to generators/client/templates/react/src/main/webapp/app/shared/reducers/locale.ts.ejs
diff --git a/generators/client/templates/react/src/main/webapp/app/shared/util/date-utils.ts.ejs b/generators/client/templates/react/src/main/webapp/app/shared/util/date-utils.ts.ejs
index 20cf73a5bb..0a506b568d 100644
--- a/generators/client/templates/react/src/main/webapp/app/shared/util/date-utils.ts.ejs
+++ b/generators/client/templates/react/src/main/webapp/app/shared/util/date-utils.ts.ejs
@@ -1,6 +1,6 @@
 import * as moment from 'moment';
 
-import { APP_LOCAL_DATETIME_FORMAT } from '../../config/constants';
+import { APP_LOCAL_DATETIME_FORMAT } from 'app/config/constants';
 
 export const convertDateTimeFromServer = date =>
   date ? moment(date).format(APP_LOCAL_DATETIME_FORMAT) : null;
diff --git a/generators/client/templates/react/tsconfig.json.ejs b/generators/client/templates/react/tsconfig.json.ejs
index 8e3b5bedac..8b62467096 100644
--- a/generators/client/templates/react/tsconfig.json.ejs
+++ b/generators/client/templates/react/tsconfig.json.ejs
@@ -17,6 +17,10 @@
     ],
     "allowJs": true,
     "checkJs": true,
+    "baseUrl": "./",
+    "paths": {
+        "app/*": ["<%= MAIN_SRC_DIR %>app/*"]
+    },
     "importHelpers": true
   },
   "include": [
diff --git a/generators/client/templates/react/tslint.json.ejs b/generators/client/templates/react/tslint.json.ejs
index 18969a80ce..498f05e4c6 100644
--- a/generators/client/templates/react/tslint.json.ejs
+++ b/generators/client/templates/react/tslint.json.ejs
@@ -135,7 +135,7 @@
     "no-unused-expression": [true, "allow-fast-null-checks"],
     "no-use-before-declare": true,
     "no-var-keyword": true,
-    "no-implicit-dependencies": [true, "dev"],
+    "no-implicit-dependencies": [false, "dev"],
     "object-literal-sort-keys": false,
     "one-line": [
       true,
@@ -191,7 +191,7 @@
       "severity": "error"
     },
     "ban-types": [true, ["Object", "Use {} instead."]],
-    "no-submodule-imports": [true, "uuid/v4", "react-icons/lib/fa"],
+    "no-submodule-imports": [true, "uuid/v4", "react-icons/lib/fa", "app"],
 
     "ter-arrow-body-style": [true],
     "ter-no-irregular-whitespace": [true],
diff --git a/generators/client/templates/react/webpack/webpack.common.js.ejs b/generators/client/templates/react/webpack/webpack.common.js.ejs
index 99c43056fb..143fd5a21c 100644
--- a/generators/client/templates/react/webpack/webpack.common.js.ejs
+++ b/generators/client/templates/react/webpack/webpack.common.js.ejs
@@ -21,13 +21,17 @@ const CopyWebpackPlugin = require('copy-webpack-plugin');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 
 const utils = require('./utils.js');
+
 module.exports = options => ({
   cache: options.env !== 'production',
   resolve: {
     extensions: [
       '.js', '.jsx', '.ts', '.tsx', '.json'
     ],
-    modules: ['node_modules']
+    modules: ['node_modules'],
+    alias: {
+      app: utils.root('<%= MAIN_SRC_DIR %>app/')
+    }
   },
   module: {
     rules: [
diff --git a/generators/entity-client/files.js b/generators/entity-client/files.js
index 5467eccf30..934daeff6c 100644
--- a/generators/entity-client/files.js
+++ b/generators/entity-client/files.js
@@ -171,6 +171,10 @@ const reactFiles = {
                     file: 'entities/entity.reducer.ts',
                     renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.reducer.ts`
                 },
+                {
+                    file: 'entities/entity.model.ts',
+                    renameTo: generator => `shared/model/${generator.entityModelFileName}.model.ts`
+                },
                 {
                     file: 'entities/index.tsx',
                     renameTo: generator => `entities/${generator.entityFolderName}/index.tsx`
diff --git a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-detail.tsx.ejs b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-detail.tsx.ejs
index 331c731d66..54f22e68a9 100644
--- a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-detail.tsx.ejs
+++ b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-detail.tsx.ejs
@@ -27,7 +27,7 @@ import { FaArrowLeft } from 'react-icons/lib/fa';
 
 import { getEntity } from './<%= entityFileName %>.reducer';
 // tslint:disable-next-line:no-unused-variable
-import { APP_DATE_FORMAT, APP_LOCAL_DATE_FORMAT } from '../../config/constants';
+import { APP_DATE_FORMAT, APP_LOCAL_DATE_FORMAT } from 'app/config/constants';
 
 export interface I<%= entityReactName %>DetailProps {
   getEntity: ICrudGetAction;
diff --git a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-dialog.tsx.ejs b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-dialog.tsx.ejs
index ee81373b8d..e8cb0fbef6 100644
--- a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-dialog.tsx.ejs
+++ b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-dialog.tsx.ejs
@@ -25,7 +25,7 @@ import { FaBan, FaFloppyO } from 'react-icons/lib/fa';
 
 import { getEntity, updateEntity, createEntity } from './<%= entityFileName %>.reducer';
 // tslint:disable-next-line:no-unused-variable
-import { convertDateTimeFromServer } from '../../shared/util/date-utils';
+import { convertDateTimeFromServer } from 'app/shared/util/date-utils';
 
 export interface I<%= entityReactName %>DialogProps {
   getEntity: ICrudGetAction;
diff --git a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.model.ts.ejs b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.model.ts.ejs
index eb7f514a73..3336cb219f 100644
--- a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.model.ts.ejs
+++ b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.model.ts.ejs
@@ -16,75 +16,13 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -%>
-<%_
-const variablesWithTypes = [];
-const typeImports = new Set();
-const defaultVariablesValues = {};
-let hasUserRelationship = false;
-let tsKeyType;
-if (pkType === 'String') {
-    tsKeyType = 'string';
-} else {
-    tsKeyType = 'number';
-}
-variablesWithTypes.push(`id?: ${tsKeyType}`);
-fields.forEach(field => {
-    const fieldType = field.fieldType;
-    const fieldName = field.fieldName;
-    let tsType;
-    if (field.fieldIsEnum) {
-        tsType = fieldType;
-    } else if (fieldType === 'Boolean') {
-        tsType = 'boolean';
-        defaultVariablesValues[fieldName] = 'this.' + fieldName + ' = false;';
-    } else if (['Integer', 'Long', 'Float', 'Double', 'BigDecimal'].includes(fieldType)) {
-        tsType = 'number';
-    } else if (fieldType === 'String'  || fieldType === 'UUID') {
-        tsType = 'string';
-    } else { //(fieldType === 'byte[]' || fieldType === 'ByteBuffer') && fieldTypeBlobContent === 'any' || (fieldType === 'byte[]' || fieldType === 'ByteBuffer') && fieldTypeBlobContent === 'image' || fieldType === 'LocalDate'
-        tsType = 'any';
-        if (['byte[]', 'ByteBuffer'].includes(fieldType) && field.fieldTypeBlobContent !== 'text') {
-            variablesWithTypes.push(`${fieldName}ContentType?: string`);
-        }
-    }
-    variablesWithTypes.push(`${fieldName}?: ${tsType}`);
-});
-relationships.forEach(relationship => {
-    let fieldType;
-    let fieldName;
-    const relationshipType = relationship.relationshipType;
-    if (relationshipType === 'one-to-many' || relationshipType === 'many-to-many') {
-        if (relationship.otherEntityAngularName === 'User') {
-            fieldType = 'IUser[]';
-            hasUserRelationship = true;
-        } else {
-            fieldType = `I${relationship.otherEntityAngularName}[]`;
-            typeImports.add(`import { I${relationship.otherEntityAngularName} } from './${relationship.otherEntityModulePath}.model'`);
-        }
-        fieldName = relationship.relationshipFieldNamePlural;
-    } else {
-        if (dto === 'no') {
-            if (relationship.otherEntityAngularName === 'User') {
-                fieldType = 'IUser';
-                hasUserRelationship = true;
-            } else {
-                fieldType = `I${relationship.otherEntityAngularName}`;
-                typeImports.add(`import { I${relationship.otherEntityAngularName} } from './${relationship.otherEntityModulePath}.model'`);
-            }
-            fieldName = relationship.relationshipFieldName;
-        } else {
-            fieldType = tsKeyType;
-            fieldName = `${relationship.relationshipFieldName}Id`;
-        }
-    }
-    variablesWithTypes.push(`${fieldName}?: ${fieldType}`);
-});
-_%>
-<%_ if (hasUserRelationship) { _%>
-import { IUser } from '../user/user.model';
-<%_ } _%>
-<%_ typeImports.forEach(typeImport => { _%>
-<%- typeImport %>;
+<%
+const variablesWithTypes = generateEntityClientFields(pkType, fields, relationships, dto);
+const typeImports = generateEntityClientImports(relationships, dto);
+const defaultVariablesValues = generateEntityClientFieldDefaultValues(fields);
+%>
+<%_ typeImports.forEach( (importedPath, importedType) => { _%>
+import { <%- importedType %> } from '<%- importedPath %>';
 <%_ }); _%>
 
 <%_ const enumsAlreadyDeclared = [];
diff --git a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.reducer.ts.ejs b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.reducer.ts.ejs
index 54fa4abb20..a689bfee5c 100644
--- a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.reducer.ts.ejs
+++ b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.reducer.ts.ejs
@@ -25,10 +25,10 @@
     let entityActionNamePlural = entityInstancePlural.toUpperCase();
 _%>
 import axios from 'axios';
-import { ICrudGetAction, ICrudPutAction, ICrudDeleteAction } from 'react-jhipster';
+import { ICrudGetAction, ICrudGetAllAction, ICrudPutAction, ICrudDeleteAction } from 'react-jhipster';
 
-import { REQUEST, SUCCESS, FAILURE } from '../../reducers/action-type.util';
-import { messages, SERVER_API_URL } from '../../config/constants';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
+import { messages, SERVER_API_URL } from 'app/config/constants';
 <%_ if (!(applicationType === 'gateway' && locals.microserviceName) && authenticationType !== 'uaa') { _%>
 
 <%_ } _%>
@@ -46,7 +46,8 @@ export const ACTION_TYPES = {
     const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
     const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
    _%>
-  FETCH_<%= otherEntityNamePlural %>: '<%= otherEntityNamePlural %>/FETCH_<%= otherEntityNamePlural %>',
+  // TODO: this should be replaced by using the action and state from the related entity
+  FETCH_<%= otherEntityNamePlural.toUpperCase() %>: '<%= otherEntityNamePlural %>/FETCH_<%= otherEntityNamePlural.toUpperCase() %>',
   <%_ } _%>
   FETCH_<%= entityActionName %>:  '<%= entityInstance %>/FETCH_<%= entityActionName %>',
   CREATE_<%= entityActionName %>: '<%= entityInstance %>/CREATE_<%= entityActionName %>',
@@ -76,7 +77,7 @@ export default (state = initialState, action) => {
     const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
     const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
 _%>
-    case REQUEST(ACTION_TYPES.FETCH_<%= otherEntityNamePlural %>):
+    case REQUEST(ACTION_TYPES.FETCH_<%= otherEntityNamePlural.toUpperCase() %>):
 <%_ } _%>
     case REQUEST(ACTION_TYPES.FETCH_<%= entityActionNamePlural %>):
     <%_ if (searchEngine === 'elasticsearch') { _%>
@@ -102,7 +103,7 @@ _%>
     const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
     const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
 _%>
-    case FAILURE(ACTION_TYPES.FETCH_<%= otherEntityNamePlural %>):
+    case FAILURE(ACTION_TYPES.FETCH_<%= otherEntityNamePlural.toUpperCase() %>):
 <%_ } _%>
     case FAILURE(ACTION_TYPES.FETCH_<%= entityActionNamePlural %>):
     <%_ if (searchEngine === 'elasticsearch') { _%>
@@ -123,7 +124,7 @@ _%>
     const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
     const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
 _%>
-    case SUCCESS(ACTION_TYPES.FETCH_<%= otherEntityNamePlural %>):
+    case SUCCESS(ACTION_TYPES.FETCH_<%= otherEntityNamePlural.toUpperCase() %>):
       return {
         ...state,
         loading: false,
@@ -181,19 +182,20 @@ const apiSearchUrl = <% if (applicationType === 'gateway' && locals.microservice
   const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
   const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
 _%>
-export const get<%= otherEntityNamePlural %>: ICrudGetAction = () => ({
-  type: ACTION_TYPES.FETCH_<%= otherEntityNamePlural %>,
+// TODO use camelcase
+export const get<%= otherEntityNamePlural %>: ICrudGetAllAction = () => ({
+  type: ACTION_TYPES.FETCH_<%= otherEntityNamePlural.toUpperCase() %>,
   payload: axios.get(`/api/<%= otherEntityNamePlural %>?cacheBuster=${new Date().getTime()}`)
 });
 
 <%_ } _%>
-export const getEntities: ICrudGetAction = (page, size, sort) => ({
+export const getEntities: ICrudGetAllAction = (page, size, sort) => ({
   type: ACTION_TYPES.FETCH_<%= entityActionNamePlural %>,
   payload: axios.get(`${apiUrl}?cacheBuster=${new Date().getTime()}`)
 });
 <%_ if (searchEngine === 'elasticsearch') { _%>
 
-export const getSearchEntities: ICrudGetAction = query => ({
+export const getSearchEntities: ICrudGetAllAction = query => ({
   type: ACTION_TYPES.SEARCH_<%= entityActionNamePlural %>,
   payload: axios.get(`${apiSearchUrl}?query=` + query)
 });
diff --git a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs
index bc5e347469..03d1e3ff90 100644
--- a/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs
+++ b/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs
@@ -25,7 +25,7 @@ import { AvForm, AvGroup, AvInput } from 'availity-reactstrap-validation';
 <%_ } _%>
 // TODO import TextFormat only when fieldContainsDate
 // tslint:disable-next-line:no-unused-variable
-import { Translate, translate, ICrudGetAction, TextFormat } from 'react-jhipster';
+import { Translate, translate, ICrudGetAllAction, TextFormat } from 'react-jhipster';
 import { FaPlus, FaEye, FaPencil, FaTrash<% if (searchEngine === 'elasticsearch') { %>, FaSearch<% } %> } from 'react-icons/lib/fa';
 
 import {
@@ -38,19 +38,19 @@ import {
   getEntities
 } from './<%= entityFileName %>.reducer';
  // tslint:disable-next-line:no-unused-variable
-import { APP_DATE_FORMAT, APP_LOCAL_DATE_FORMAT } from '../../config/constants';
+import { APP_DATE_FORMAT, APP_LOCAL_DATE_FORMAT } from 'app/config/constants';
 
 export interface I<%= entityReactName %>Props {
-  getEntities: ICrudGetAction;
+  getEntities: ICrudGetAllAction;
   <%_ if (searchEngine === 'elasticsearch') { _%>
-  getSearchEntities: ICrudGetAction;
+  getSearchEntities: ICrudGetAllAction;
   <%_ } _%>
   <%=entityInstancePlural %>: any[];
   <%_ for (idx in relationships) {
     const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural;
     const otherEntityNamePlural = relationships[idx].otherEntityNamePlural;
   _%>
-  get<%= otherEntityNamePlural %>: ICrudGetAction;
+  get<%= otherEntityNamePlural %>: ICrudGetAllAction;
   <%_ } _%>
   match: any;
 }
diff --git a/generators/generator-base-private.js b/generators/generator-base-private.js
index dcd84ae60e..f3e27d79e5 100644
--- a/generators/generator-base-private.js
+++ b/generators/generator-base-private.js
@@ -856,7 +856,7 @@ module.exports = class extends Generator {
      * @param {string} dto - dto
      * @returns typeImports: Map
      */
-    generateEntityClientImports(relationships, dto) {
+    generateEntityClientImports(relationships, dto, clientFramework = this.clientFramework) {
         const typeImports = new Map();
 
         relationships.forEach((relationship) => {
@@ -880,7 +880,7 @@ module.exports = class extends Generator {
                 const importType = `I${otherEntityAngularName}`;
                 let importPath;
                 if (otherEntityAngularName === 'User') {
-                    importPath = 'app/core/user/user.model';
+                    importPath = clientFramework === 'angularX' ? 'app/core/user/user.model' : './user.model';
                 } else {
                     importPath = `./${relationship.otherEntityFileName}.model`;
                 }
diff --git a/generators/generator-base.js b/generators/generator-base.js
index 7ff38fba17..45bad63087 100644
--- a/generators/generator-base.js
+++ b/generators/generator-base.js
@@ -280,13 +280,13 @@ module.exports = class extends PrivateBase {
                     ]
                 }, this);
 
-                const indexReducerPath = `${CLIENT_MAIN_SRC_DIR}app/reducers/index.ts`;
+                const indexReducerPath = `${CLIENT_MAIN_SRC_DIR}app/shared/reducers/index.ts`;
 
                 jhipsterUtils.rewriteFile({
                     file: indexReducerPath,
                     needle: 'jhipster-needle-add-reducer-import',
                     splicable: [
-                        this.stripMargin(`|import ${entityInstance} from '../entities/${entityFolderName}/${entityFileName}.reducer';`)
+                        this.stripMargin(`|import ${entityInstance} from 'app/entities/${entityFolderName}/${entityFileName}.reducer';`)
                     ]
                 }, this);
 
diff --git a/generators/server/files.js b/generators/server/files.js
index 795cabf789..c17d3cb9f1 100644
--- a/generators/server/files.js
+++ b/generators/server/files.js
@@ -319,10 +319,6 @@ function writeFiles() {
                 this.template(`${SERVER_MAIN_SRC_DIR}package/security/oauth2/OAuth2TokenEndpointClientAdapter.java.ejs`, `${javaDir}security/oauth2/OAuth2TokenEndpointClientAdapter.java`);
                 this.template(`${SERVER_MAIN_SRC_DIR}package/security/oauth2/UaaTokenEndpointClient.java.ejs`, `${javaDir}security/oauth2/UaaTokenEndpointClient.java`);
             }
-            if (this.authenticationType === 'oauth2') {
-                this.template(`${SERVER_MAIN_SRC_DIR}package/config/OAuth2Configuration.java.ejs`, `${javaDir}config/OAuth2Configuration.java`);
-                this.template(`${SERVER_MAIN_SRC_DIR}package/security/OAuth2AuthenticationSuccessHandler.java.ejs`, `${javaDir}security/OAuth2AuthenticationSuccessHandler.java`);
-            }
         },
 
         writeServerMicroserviceFiles() {
diff --git a/generators/server/templates/src/main/java/package/config/DatabaseConfiguration.java.ejs b/generators/server/templates/src/main/java/package/config/DatabaseConfiguration.java.ejs
index 0aeb83f53c..542b9727fb 100644
--- a/generators/server/templates/src/main/java/package/config/DatabaseConfiguration.java.ejs
+++ b/generators/server/templates/src/main/java/package/config/DatabaseConfiguration.java.ejs
@@ -40,8 +40,7 @@ import io.github.jhipster.domain.util.JSR310DateConverters.DateToZonedDateTimeCo
 import io.github.jhipster.domain.util.JSR310DateConverters.ZonedDateTimeToDateConverter;
 <%_ } _%>
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-<%_ if (databaseType === 'mongodb') { _%>
+import org.slf4j.LoggerFactory;<% if (databaseType === 'mongodb') { %>
 import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
 import org.springframework.boot.autoconfigure.mongo.MongoProperties;<% } %><% if (databaseType === 'couchbase') { %>
 import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;<% } %><% if (databaseType === 'sql') { %>
@@ -66,9 +65,6 @@ import org.springframework.data.mongodb.config.EnableMongoAuditing;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
 import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
-    <%_ if (searchEngine === 'elasticsearch') { _%>
-import org.springframework.data.mongodb.repository.MongoRepository;
-    <%_ } _%>
 import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;<% } %><% if (databaseType === 'couchbase') { %>
 import org.springframework.data.convert.ReadingConverter;
 import org.springframework.data.convert.WritingConverter;


Test patch:
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/config/notification-middleware.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/config/notification-middleware.spec.ts.ejs
index 87184bd3a0..9c7235c685 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/config/notification-middleware.spec.ts.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/config/notification-middleware.spec.ts.ejs
@@ -4,7 +4,7 @@ import promiseMiddleware from 'redux-promise-middleware';
 // import * as toaster from 'react-toastify';
 // import * as sinon from 'sinon';
 
-import notificationMiddleware from '../../../../../main/webapp/app/config/notification-middleware';
+import notificationMiddleware from 'app/config/notification-middleware';
 
 describe('Notification Middleware', () => {
   let store;
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/reducers/activate.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/activate/activate.reducer.spec.ts.ejs
similarity index 83%
rename from generators/client/templates/react/src/test/javascript/spec/app/reducers/activate.spec.ts.ejs
rename to generators/client/templates/react/src/test/javascript/spec/app/modules/account/activate/activate.reducer.spec.ts.ejs
index bbfb48eb87..e9cee1872e 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/reducers/activate.spec.ts.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/activate/activate.reducer.spec.ts.ejs
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
-import { SUCCESS, FAILURE } from '../../../../../main/webapp/app/reducers/action-type.util';
+import { SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
-import activate, { ACTION_TYPES } from '../../../../../main/webapp/app/reducers/activate';
+import activate, { ACTION_TYPES } from 'app/modules/account/activate/activate.reducer';
 
 describe('Activate reducer tests', () => {
 
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/modules/account/password/password.reducer.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/password/password.reducer.spec.ts.ejs
new file mode 100644
index 0000000000..e10cdcee8b
--- /dev/null
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/password/password.reducer.spec.ts.ejs
@@ -0,0 +1,45 @@
+import { expect } from 'chai';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
+
+import password, { ACTION_TYPES } from 'app/modules/account/password/password.reducer';
+
+describe('Password reducer tests', () => {
+  describe('Common tests', () => {
+    it('should return the initial state', () => {
+      const toTest = password(undefined, {});
+      expect(toTest).to.contain({
+        loading: false,
+        errorMessage: null,
+        updateSuccess: false,
+        updateFailure: false
+      });
+    });
+  });
+
+  describe('Password update', () => {
+    it('should detect a request', () => {
+      const toTest = password(undefined, { type: REQUEST(ACTION_TYPES.UPDATE_PASSWORD) });
+      expect(toTest).to.contain({
+        updateSuccess: false,
+        updateFailure: false,
+        loading: true
+      });
+    });
+    it('should detect a success', () => {
+      const toTest = password(undefined, { type: SUCCESS(ACTION_TYPES.UPDATE_PASSWORD) });
+      expect(toTest).to.contain({
+        updateSuccess: true,
+        updateFailure: false,
+        loading: false
+      });
+    });
+    it('should detect a failure', () => {
+      const toTest = password(undefined, { type: FAILURE(ACTION_TYPES.UPDATE_PASSWORD) });
+      expect(toTest).to.contain({
+        updateSuccess: false,
+        updateFailure: true,
+        loading: false
+      });
+    });
+  });
+});
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/reducers/register.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.reducer.spec.ts.ejs
similarity index 88%
rename from generators/client/templates/react/src/test/javascript/spec/app/reducers/register.spec.ts.ejs
rename to generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.reducer.spec.ts.ejs
index 9c8fbe6119..c9468638d3 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/reducers/register.spec.ts.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.reducer.spec.ts.ejs
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
 
-import { FAILURE, REQUEST, SUCCESS } from '../../../../../main/webapp/app/reducers/action-type.util';
-import register, { ACTION_TYPES } from '../../../../../main/webapp/app/reducers/register';
+import { FAILURE, REQUEST, SUCCESS } from 'app/shared/reducers/action-type.util';
+import register, { ACTION_TYPES } from 'app/modules/account/register/register.reducer';
 
 describe('Creating account tests', () => {
   const initialState = {
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/account/register/register.spec.tsx b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.spec.tsx.ejs
similarity index 69%
rename from generators/client/templates/react/src/test/javascript/spec/app/account/register/register.spec.tsx
rename to generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.spec.tsx.ejs
index 9e629a2179..cb69ff17d8 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/account/register/register.spec.tsx
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/register/register.spec.tsx.ejs
@@ -1,30 +1,35 @@
-// import * as React from 'react';
-// import * as Enzyme from 'enzyme';
-// import * as EnzymeAdapter from 'enzyme-adapter-react-16';
-// import axios from 'axios';
-// import { expect } from 'chai';
-// import configureStore from 'redux-mock-store';
-// import { spy, sandbox } from 'sinon';
-
-// import RegisterPage from '../../../../../../main/webapp/app/modules/account/register/register';
-
-/*
-describe('RegisterComponent', () => {
+/* import * as React from 'react';
+import { shallow } from 'enzyme';
+import axios from 'axios';
+import { expect } from 'chai';
+import configureStore from 'redux-mock-store';
+import { spy, sandbox } from 'sinon';
+
+import { RegisterPage } from 'app/modules/account/register/register';
+
+describe.only('RegisterComponent', () => {
   describe('RegisterPage', () => {
-    Enzyme.configure({ adapter: new EnzymeAdapter() });
     let mountedWrapper;
     let localSandbox;
     const mockStore = configureStore();
+    const handleRegisterSpy = spy();
 
     const wrapper = () => {
       localSandbox = sandbox.create();
-      const localeSpy = spy();
       const initialState = {};
-      const store = mockStore(initialState);
+      // const store = mockStore(initialState);
+      const props = {
+        handleRegister: handleRegisterSpy,
+        reset: spy(),
+        registrationSuccess: false,
+        registrationFailure: false,
+        errorMessage: '',
+        currentLocale: 'en'
+      };
 
       if (!mountedWrapper) {
-        mountedWrapper = Enzyme.shallow(
-          <RegisterPage store={store} onLocaleChange={localeSpy}/>
+        mountedWrapper = shallow(
+          <RegisterPage {...props}/>
         );
       }
 
@@ -39,12 +44,10 @@ describe('RegisterComponent', () => {
     };
 
     const fillForm = (wrappedRegister, values = defaultInput) => {
-      const dive = wrappedRegister.dive();
-
-      dive.find({ name: 'username' }).simulate('change', { target: { value: values.username } });
-      dive.find({ name: 'email' }).simulate('change', { target: { value: values.email } });
-      dive.find({ name: 'firstPassword' }).simulate('change', { target: { value: values.firstPassword } });
-      dive.find({ name: 'secondPassword' }).simulate('change', { target: { value: values.secondPassword } });
+      wrappedRegister.find({ name: 'username' }).simulate('change', { target: { value: values.username } });
+      wrappedRegister.find({ name: 'email' }).simulate('change', { target: { value: values.email } });
+      wrappedRegister.find({ name: 'firstPassword' }).simulate('change', { target: { value: values.firstPassword } });
+      wrappedRegister.find({ name: 'secondPassword' }).simulate('change', { target: { value: values.secondPassword } });
     };
 
     beforeEach(() => {
@@ -59,11 +62,10 @@ describe('RegisterComponent', () => {
       };
 
       fillForm(register, values);
-      register.dive().find('#register-submit').simulate('click');
+      register.find('#register-submit').simulate('click');
 
       // Both should be false since you can't submit an invalid form.
-      expect(register.props().registrationSuccess).to.be.equals(false);
-      expect(register.props().registrationFailure).to.be.equals(false);
+      expect(handleRegisterSpy.called).to.equals(false);
     });
 
     it('should update registration success to true after creating an account', async () => {
@@ -72,10 +74,11 @@ describe('RegisterComponent', () => {
       const resolved = new Promise(r => r({ status: 201 }));
       localSandbox.stub(axios, 'get').returns(resolved);
 
-      register.dive().find('#register-submit').simulate('click');
+      register.find('#register-submit').simulate('click');
 
-      expect(register.props().registrationSuccess).to.be.equals(true);
-      expect(register.props().registrationFailure).to.be.equals(false);
+      expect(handleRegisterSpy.called).to.equals(true);
+      // expect(register.props().registrationSuccess).to.equal(true);
+      // expect(register.props().registrationFailure).to.equal(false);
     });
 
     it('should notify of user existence upon 400/login already in use', () => {
@@ -138,4 +141,4 @@ describe('RegisterComponent', () => {
 
   });
 });
-*/
+ */
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/modules/account/settings/settings.reducer.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/settings/settings.reducer.spec.ts.ejs
new file mode 100644
index 0000000000..ee226f2b28
--- /dev/null
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/account/settings/settings.reducer.spec.ts.ejs
@@ -0,0 +1,45 @@
+import { expect } from 'chai';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
+
+import account, { ACTION_TYPES } from 'app/modules/account/settings/settings.reducer';
+
+describe('Settings reducer tests', () => {
+  describe('Common tests', () => {
+    it('should return the initial state', () => {
+      const toTest = account(undefined, {});
+      expect(toTest).to.contain({
+        loading: false,
+        errorMessage: null,
+        updateSuccess: false,
+        updateFailure: false
+      });
+    });
+  });
+
+  describe('Settings update', () => {
+    it('should detect a request', () => {
+      const toTest = account(undefined, { type: REQUEST(ACTION_TYPES.UPDATE_ACCOUNT) });
+      expect(toTest).to.contain({
+        updateSuccess: false,
+        updateFailure: false,
+        loading: true
+      });
+    });
+    it('should detect a success', () => {
+      const toTest = account(undefined, { type: SUCCESS(ACTION_TYPES.UPDATE_ACCOUNT) });
+      expect(toTest).to.contain({
+        updateSuccess: true,
+        updateFailure: false,
+        loading: false
+      });
+    });
+    it('should detect a failure', () => {
+      const toTest = account(undefined, { type: FAILURE(ACTION_TYPES.UPDATE_ACCOUNT) });
+      expect(toTest).to.contain({
+        updateSuccess: false,
+        updateFailure: true,
+        loading: false
+      });
+    });
+  });
+});
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/reducers/user-management.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/modules/administration/user-management/user-management.reducer.spec.ts.ejs
similarity index 95%
rename from generators/client/templates/react/src/test/javascript/spec/app/reducers/user-management.spec.ts.ejs
rename to generators/client/templates/react/src/test/javascript/spec/app/modules/administration/user-management/user-management.reducer.spec.ts.ejs
index 627a2cbb59..1227b011e6 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/reducers/user-management.spec.ts.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/modules/administration/user-management/user-management.reducer.spec.ts.ejs
@@ -1,8 +1,8 @@
 
 import { expect } from 'chai';
-import { REQUEST, SUCCESS, FAILURE } from '../../../../../main/webapp/app/reducers/action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
-import userManagement, { ACTION_TYPES } from '../../../../../main/webapp/app/reducers/user-management';
+import userManagement, { ACTION_TYPES } from 'app/modules/administration/user-management/user-management.reducer';
 
 describe('User managment reducer tests', () => {
   function isEmpty(element): boolean {
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/reducers/account.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/reducers/account.spec.ts.ejs
deleted file mode 100644
index f5957632ce..0000000000
--- a/generators/client/templates/react/src/test/javascript/spec/app/reducers/account.spec.ts.ejs
+++ /dev/null
@@ -1,84 +0,0 @@
-import { expect } from 'chai';
-import { REQUEST, SUCCESS, FAILURE } from '../../../../../main/webapp/app/reducers/action-type.util';
-
-import account, { ACTION_TYPES } from '../../../../../main/webapp/app/reducers/account';
-
-describe('Account reducer tests', () => {
-  function isAccountEmpty(state): boolean {
-    return Object.keys(state.account).length === 0;
-  }
-
-  describe('Common tests', () => {
-    it('should return the initial state', () => {
-      const toTest = account(undefined, {});
-      expect(toTest).to.contain({
-        loading: false,
-        errorMessage: null,
-        updateSuccess: false,
-        updateFailure: false
-      });
-      expect(isAccountEmpty(toTest));
-    });
-  });
-
-  describe('Account update', () => {
-    it('should detect a request', () => {
-      const toTest = account(undefined, { type: REQUEST(ACTION_TYPES.UPDATE_ACCOUNT) });
-      expect(toTest).to.contain({
-        updateSuccess: false,
-        updateFailure: false,
-        loading: true
-      });
-      expect(isAccountEmpty(toTest));
-    });
-    it('should detect a success', () => {
-      const payloadValue = { data: 'fancy payload' };
-      const toTest = account(undefined, { type: SUCCESS(ACTION_TYPES.UPDATE_ACCOUNT), payload: payloadValue });
-      expect(toTest).to.contain({
-        updateSuccess: true,
-        updateFailure: false,
-        loading: false,
-        account: 'fancy payload'
-      });
-    });
-    it('should detect a failure', () => {
-      const toTest = account(undefined, { type: FAILURE(ACTION_TYPES.UPDATE_ACCOUNT) });
-      expect(toTest).to.contain({
-        updateSuccess: false,
-        updateFailure: true,
-        loading: false
-      });
-      expect(isAccountEmpty(toTest));
-    });
-  });
-
-  describe('Password update', () => {
-    it('should detect a request', () => {
-      const toTest = account(undefined, { type: REQUEST(ACTION_TYPES.UPDATE_PASSWORD) });
-      expect(toTest).to.contain({
-        updateSuccess: false,
-        updateFailure: false,
-        loading: true
-      });
-      expect(isAccountEmpty(toTest));
-    });
-    it('should detect a success', () => {
-      const toTest = account(undefined, { type: SUCCESS(ACTION_TYPES.UPDATE_PASSWORD) });
-      expect(toTest).to.contain({
-        updateSuccess: true,
-        updateFailure: false,
-        loading: false
-      });
-      expect(isAccountEmpty(toTest));
-    });
-    it('should detect a failure', () => {
-      const toTest = account(undefined, { type: FAILURE(ACTION_TYPES.UPDATE_PASSWORD) });
-      expect(toTest).to.contain({
-        updateSuccess: false,
-        updateFailure: true,
-        loading: false
-      });
-      expect(isAccountEmpty(toTest));
-    });
-  });
-});
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/shared/layout/header.spec.tsx.ejs b/generators/client/templates/react/src/test/javascript/spec/app/shared/layout/header.spec.tsx.ejs
index 4f8a754fe1..a24bed80bc 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/shared/layout/header.spec.tsx.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/shared/layout/header.spec.tsx.ejs
@@ -10,7 +10,7 @@ import {
   Nav, NavItem, NavbarBrand
 } from 'reactstrap';
 
-import Header from '../../../../../../main/webapp/app/shared/layout/header/header';
+import Header from 'app/shared/layout/header/header';
 
 describe('Header', () => {
   let mountedWrapper;
diff --git a/generators/client/templates/react/src/test/javascript/spec/app/reducers/authentication.spec.ts.ejs b/generators/client/templates/react/src/test/javascript/spec/app/shared/reducers/authentication.spec.ts.ejs
similarity index 95%
rename from generators/client/templates/react/src/test/javascript/spec/app/reducers/authentication.spec.ts.ejs
rename to generators/client/templates/react/src/test/javascript/spec/app/shared/reducers/authentication.spec.ts.ejs
index e310bd07c4..f15b4a86ab 100644
--- a/generators/client/templates/react/src/test/javascript/spec/app/reducers/authentication.spec.ts.ejs
+++ b/generators/client/templates/react/src/test/javascript/spec/app/shared/reducers/authentication.spec.ts.ejs
@@ -1,7 +1,7 @@
 import { expect } from 'chai';
-import { REQUEST, SUCCESS, FAILURE } from '../../../../../main/webapp/app/reducers/action-type.util';
+import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
 
-import authentication, { ACTION_TYPES } from '../../../../../main/webapp/app/reducers/authentication';
+import authentication, { ACTION_TYPES } from 'app/shared/reducers/authentication';
 
 describe('Authentication reducer tests', () => {
   function isAccountEmpty(state): boolean {
diff --git a/generators/client/templates/react/webpack/webpack.test.js.ejs b/generators/client/templates/react/webpack/webpack.test.js.ejs
index 053d799932..0e9197aaab 100644
--- a/generators/client/templates/react/webpack/webpack.test.js.ejs
+++ b/generators/client/templates/react/webpack/webpack.test.js.ejs
@@ -20,6 +20,7 @@ const webpack = require('webpack');
 const path = require('path');
 const webpackMerge = require('webpack-merge');
 const commonConfig = require('./webpack.common.js');
+const utils = require('./utils.js');
 
 const ENV = 'development';
 
@@ -69,7 +70,10 @@ module.exports = {
     extensions: [
       '.js', '.jsx', '.ts', '.tsx', '.json'
     ],
-    modules: ['node_modules']
+    modules: ['node_modules'],
+    alias: {
+      app: utils.root('<%= MAIN_SRC_DIR %>app/')
+    }
   },
   plugins: [
     new webpack.SourceMapDevToolPlugin({
diff --git a/generators/entity-client/templates/react/src/test/javascript/spec/app/entities/entity-reducer.spc.ts.ejs b/generators/entity-client/templates/react/src/test/javascript/spec/app/entities/entity-reducer.spc.ts.ejs
new file mode 100644
index 0000000000..020d61ffd3
--- /dev/null
+++ b/generators/entity-client/templates/react/src/test/javascript/spec/app/entities/entity-reducer.spc.ts.ejs
@@ -0,0 +1,132 @@
+import axios from 'axios';
+import { expect } from 'chai';
+import configureStore from 'redux-mock-store';
+import promiseMiddleware from 'redux-promise-middleware';
+import thunk from 'redux-thunk';
+import * as sinon from 'sinon';
+
+import reducer, { ACTION_TYPES, getSystemProperties, getSystemPropertyByKey } from 'app/reducers/system-property';
+import { REQUEST, SUCCESS, FAILURE } from 'app/reducers/action-type.util';
+import { getDefaultSystemProperties } from '../utils';
+
+// tslint:disable no-invalid-template-strings
+describe('system property reducer', () => {
+  describe('systemPropertyReducer', () => {
+    const initialState = {
+      loading: false,
+      errorMessage: null,
+      systemPropertiesByKey: {},
+      systemProperty: null,
+      updateSuccess: false
+    };
+    const data = {
+      id: 1,
+      key: 'KEY_1'
+    };
+    it('should return initialState when invalid action specified', () => {
+      expect(reducer(initialState, { type: 'INVALID' })).to.eql(initialState);
+    });
+    it('should return initialState with loading for FETCH_PENDING', () => {
+      expect(reducer(initialState, { type: REQUEST(ACTION_TYPES.FETCH_PROPERTIES) })).to.eql({ ...initialState, loading: true });
+    });
+    it('should return initialState with errrMessage for FETCH_REJECTED', () => {
+      expect(reducer(initialState, { type: FAILURE(ACTION_TYPES.FETCH_PROPERTIES), payload: 'ERROR' })).to.eql({
+        ...initialState,
+        errorMessage: 'ERROR'
+      });
+    });
+    it('should reduce systemProperties array into systemPropertiesByKey for FETCH_PROPERTIES', () => {
+      const action = {
+        type: SUCCESS(ACTION_TYPES.FETCH_PROPERTIES),
+        payload: {
+          data: [
+            {
+              id: 1,
+              key: 'KEY_1'
+            },
+            {
+              id: 2,
+              key: 'KEY_2'
+            }
+          ]
+        }
+      };
+      const expected = {
+        KEY_1: {
+          id: 1,
+          key: 'KEY_1'
+        },
+        KEY_2: {
+          id: 2,
+          key: 'KEY_2'
+        }
+      };
+      expect(reducer(initialState, action)).to.eql({ ...initialState, systemPropertiesByKey: expected });
+    });
+    it('should return initialState with systemProperty for FETCH_PROPERTY', () => {
+      expect(reducer(initialState, { type: SUCCESS(ACTION_TYPES.FETCH_PROPERTY), payload: { data } })).to.eql({
+        ...initialState,
+        systemProperty: data
+      });
+    });
+    it('should return initialState with systemProperty for CREATE_PROPERTY', () => {
+      expect(reducer(initialState, { type: SUCCESS(ACTION_TYPES.CREATE_PROPERTY), payload: { data } })).to.eql({
+        ...initialState,
+        systemProperty: data,
+        updateSuccess: true
+      });
+    });
+    it('should return initialState with systemProperty for UPDATE_PROPERTY', () => {
+      expect(reducer(initialState, { type: SUCCESS(ACTION_TYPES.UPDATE_PROPERTY), payload: { data } })).to.eql({
+        ...initialState,
+        systemProperty: data,
+        updateSuccess: true
+      });
+    });
+    it('should return initialState with updateSuccess for DELETE_PROPERTY', () => {
+      expect(reducer(initialState, { type: SUCCESS(ACTION_TYPES.DELETE_PROPERTY) })).to.eql({
+        ...initialState,
+        systemProperty: {},
+        updateSuccess: true
+      });
+    });
+  });
+  describe('system property actions', () => {
+    let store;
+
+    beforeEach(() => {
+      const mockStore = configureStore([thunk, promiseMiddleware()]);
+      store = mockStore({});
+    });
+
+    describe('getSystemProperties', () => {
+      const resolvedObject = { value: 'whatever' };
+      beforeEach(() => {
+        axios.get = sinon.stub().returns(Promise.resolve(resolvedObject));
+      });
+      it('should return a Promise', async () => {
+        const mockDispatch = val => ({ ...val, value: { data: Object.values(getDefaultSystemProperties()) } });
+        const dispatch = getSystemProperties() as any;
+        const res = await dispatch(mockDispatch);
+        expect(res).to.have.property('type', ACTION_TYPES.FETCH_PROPERTIES);
+        const local = JSON.parse(window.sessionStorage.getItem(XLI_SYS_PROPERTIES));
+        expect(local).to.eql(getDefaultSystemProperties());
+        window.sessionStorage.removeItem(XLI_SYS_PROPERTIES);
+      });
+
+      it('dispatches FETCH_PROPERTIES_PENDING and FETCH_PROPERTIES_FULFILLED actions', async () => {
+        const expectedActions = [
+          {
+            type: REQUEST(ACTION_TYPES.FETCH_PROPERTIES)
+          },
+          {
+            type: SUCCESS(ACTION_TYPES.FETCH_PROPERTIES),
+            payload: resolvedObject
+          }
+        ];
+
+        await store.dispatch(getSystemProperties()).then(() => expect(store.getActions()).to.eql(expectedActions));
+      });
+    });
+  });
+});