client.tsx 3.72 KB
Newer Older
Maxym Borodenko's avatar
Maxym Borodenko committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {routerMiddleware, ConnectedRouter} from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';
import {Provider} from 'react-redux';
import {applyMiddleware, compose, createStore} from 'redux';
import { checkAccessTokens } from 'actions/login';
import rootReducer from 'reducers/index';
import thunk from 'redux-thunk';
import {log} from 'utilities/debug';
import { I18nextProvider } from 'react-i18next';
import routes from 'ui/routes';
import renderRoutes from 'ui/renderRoutes';
import i18nClient from '../i18n/i18n-client';
import detectLocaleFromPath from '../server/middleware/detectLocaleFromPath';
import getDir from '../server/middleware/detectDirection';

// JSS & MUI
Matija Obreza's avatar
Matija Obreza committed
19
import { MuiThemeProvider } from '@material-ui/core/styles';
Maxym Borodenko's avatar
Maxym Borodenko committed
20
import theme from 'ui/theme';
21
import { configureBackendApi } from 'utilities/requestUtils';
Maxym Borodenko's avatar
Maxym Borodenko committed
22
23
24
25
26
27
28
29

declare const __PRELOADED_STATE__: any;

declare const window: Window & { devToolsExtension: any, __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any, initialLanguage: any, initialI18nStore: any };
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const initialLanguage = window.initialLanguage;
const initialI18nStore = window.initialI18nStore;
30
31
32
33
34

// document.baseURI is full URI, we take everything but the trailing slash (for "/" it is "", for "/aa/" or "/aa" it is "/aa")
const virtualPath = document.baseURI.replace(/^(https?:\/\/[^\/]+)?(.*)\/$/, '$2');
const detectedLang = initialLanguage ? initialLanguage : detectLocaleFromPath(virtualPath, window.location.pathname, 0);
const historyOptions = { basename: detectedLang !== 'en' ? `${virtualPath}/${detectedLang}` : `${virtualPath}` };
Maxym Borodenko's avatar
Maxym Borodenko committed
35
36
const history = createHistory(historyOptions);

37
38
39
// Configure axios for client
configureBackendApi({ apiUrl: `${virtualPath}/proxy` });

Maxym Borodenko's avatar
Maxym Borodenko committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const initialState = __PRELOADED_STATE__ === undefined ? {} : __PRELOADED_STATE__;
const store = composeEnhancers(applyMiddleware(thunk, routerMiddleware(history)))(createStore)(rootReducer, initialState);

if (__PRELOADED_STATE__ === undefined) {
  document.getElementsByTagName('html')[0].setAttribute('lang', detectedLang);
  document.getElementsByTagName('html')[0].setAttribute('dir', getDir(detectedLang));

  checkAccessTokens(store.dispatch)
    .then(() => {
      // no SSR
      ReactDOM.render(
          <Provider store={ store }>
              <ConnectedRouter history={ history }>
                  <I18nextProvider i18n={ i18nClient } initialLanguage={ initialLanguage } initialI18nStore={ initialI18nStore }>
                      <MuiThemeProvider theme={ theme }>
                          { renderRoutes(routes) }
                      </MuiThemeProvider>
                  </I18nextProvider>
              </ConnectedRouter>
          </Provider>,
        document.getElementById('the-app'),
      );
    })
    .catch((err) => {
      log('Oh, oh', err);
    });
} else {
    // SSR
    ReactDOM.hydrate(
        <Provider store={ store }>
            <ConnectedRouter history={ history }>
                <I18nextProvider i18n={ i18nClient } initialLanguage={ initialLanguage } initialI18nStore={ initialI18nStore }>
                    <MuiThemeProvider theme={ theme }>
                        { renderRoutes(routes) }
                    </MuiThemeProvider>
                </I18nextProvider>
            </ConnectedRouter>
        </Provider>,
        document.getElementById('the-app'),
        () => {
            // We don't need the static css any more once we have launched our application.
            log('Removing SSR-rendered styles');
            const ssStyles = document.getElementById('server-side-styles');
            ssStyles.parentNode.removeChild(ssStyles);
        },
    );
}