diff --git a/package.json b/package.json
index bd22d155..21c36f8d 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@fortawesome/react-fontawesome": "0.0.19",
"axios": "^0.18.0",
"bootstrap": "^4.1.1",
+ "bottlejs": "^1.7.1",
"chart.js": "^2.7.2",
"classnames": "^2.2.6",
"csvjson": "^5.1.0",
diff --git a/src/App.js b/src/App.js
index f7203923..dce4f6e5 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,23 +1,21 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import './App.scss';
-import Home from './common/Home';
-import MainHeader from './common/MainHeader';
import MenuLayout from './common/MenuLayout';
import CreateServer from './servers/CreateServer';
-export default function App() {
- return (
-
-
+const App = (MainHeader, Home) => () => (
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
- );
-}
+
+);
+
+export default App;
diff --git a/src/common/Home.js b/src/common/Home.js
index a3293d49..7acf4959 100644
--- a/src/common/Home.js
+++ b/src/common/Home.js
@@ -1,15 +1,13 @@
import chevronIcon from '@fortawesome/fontawesome-free-solid/faChevronRight';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
-import { isEmpty, pick, values } from 'ramda';
+import { isEmpty, values } from 'ramda';
import React from 'react';
-import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { ListGroup, ListGroupItem } from 'reactstrap';
import PropTypes from 'prop-types';
-import { resetSelectedServer } from '../servers/reducers/selectedServer';
import './Home.scss';
-export class HomeComponent extends React.Component {
+export default class Home extends React.Component {
static propTypes = {
resetSelectedServer: PropTypes.func,
servers: PropTypes.object,
@@ -50,7 +48,3 @@ export class HomeComponent extends React.Component {
);
}
}
-
-const Home = connect(pick([ 'servers' ]), { resetSelectedServer })(HomeComponent);
-
-export default Home;
diff --git a/src/common/MainHeader.js b/src/common/MainHeader.js
index 76836714..aa95cb06 100644
--- a/src/common/MainHeader.js
+++ b/src/common/MainHeader.js
@@ -2,7 +2,7 @@ import plusIcon from '@fortawesome/fontawesome-free-solid/faPlus';
import arrowIcon from '@fortawesome/fontawesome-free-solid/faChevronDown';
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import React from 'react';
-import { Link, withRouter } from 'react-router-dom';
+import { Link } from 'react-router-dom';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames';
import PropTypes from 'prop-types';
@@ -10,7 +10,7 @@ import ServersDropdown from '../servers/ServersDropdown';
import './MainHeader.scss';
import shlinkLogo from './shlink-logo-white.png';
-export class MainHeaderComponent extends React.Component {
+const MainHeader = () => class MainHeaderComponent extends React.Component {
static propTypes = {
location: PropTypes.object,
};
@@ -62,8 +62,6 @@ export class MainHeaderComponent extends React.Component {
);
}
-}
-
-const MainHeader = withRouter(MainHeaderComponent);
+};
export default MainHeader;
diff --git a/src/common/ScrollToTop.js b/src/common/ScrollToTop.js
index 789f1a33..c8624da0 100644
--- a/src/common/ScrollToTop.js
+++ b/src/common/ScrollToTop.js
@@ -1,8 +1,7 @@
import React from 'react';
-import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
-export class ScrollToTopComponent extends React.Component {
+export default class ScrollToTop extends React.Component {
static propTypes = {
location: PropTypes.object,
window: PropTypes.shape({
@@ -11,7 +10,7 @@ export class ScrollToTopComponent extends React.Component {
children: PropTypes.node,
};
static defaultProps = {
- window,
+ window: global.window,
};
componentDidUpdate(prevProps) {
@@ -26,7 +25,3 @@ export class ScrollToTopComponent extends React.Component {
return this.props.children;
}
}
-
-const ScrollToTop = withRouter(ScrollToTopComponent);
-
-export default ScrollToTop;
diff --git a/src/container/index.js b/src/container/index.js
new file mode 100644
index 00000000..2009c749
--- /dev/null
+++ b/src/container/index.js
@@ -0,0 +1,20 @@
+import Bottle from 'bottlejs';
+import { withRouter } from 'react-router-dom';
+import { connect } from 'react-redux';
+import { pick } from 'ramda';
+import App from '../App';
+import ScrollToTop from '../common/ScrollToTop';
+import MainHeader from '../common/MainHeader';
+import { resetSelectedServer } from '../servers/reducers/selectedServer';
+import Home from '../common/Home';
+import store from './store';
+
+const bottle = new Bottle();
+
+bottle.constant('store', store);
+bottle.serviceFactory('App', App, 'MainHeader', 'Home');
+bottle.serviceFactory('MainHeader', () => withRouter(MainHeader()));
+bottle.serviceFactory('ScrollToTop', () => withRouter(ScrollToTop));
+bottle.serviceFactory('Home', () => connect(pick([ 'servers' ]), { resetSelectedServer })(Home));
+
+export default bottle.container;
diff --git a/src/container/store.js b/src/container/store.js
new file mode 100644
index 00000000..0d5b2b2d
--- /dev/null
+++ b/src/container/store.js
@@ -0,0 +1,13 @@
+import ReduxThunk from 'redux-thunk';
+import { applyMiddleware, compose, createStore } from 'redux';
+import reducers from '../reducers';
+
+const composeEnhancers = process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
+ : compose;
+
+const store = createStore(reducers, composeEnhancers(
+ applyMiddleware(ReduxThunk)
+));
+
+export default store;
diff --git a/src/index.js b/src/index.js
index c0a4a375..62c93f92 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,23 +3,14 @@ import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
-import { applyMiddleware, compose, createStore } from 'redux';
-import ReduxThunk from 'redux-thunk';
import { homepage } from '../package.json';
-import App from './App';
-import './index.scss';
-import ScrollToTop from './common/ScrollToTop';
-import reducers from './reducers';
import registerServiceWorker from './registerServiceWorker';
+import container from './container';
import '../node_modules/react-datepicker/dist/react-datepicker.css';
import './common/react-tagsinput.scss';
+import './index.scss';
-const composeEnhancers = process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
- ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
- : compose;
-const store = createStore(reducers, composeEnhancers(
- applyMiddleware(ReduxThunk)
-));
+const { App, ScrollToTop, store } = container;
render(
diff --git a/yarn.lock b/yarn.lock
index c0d1c02c..14d4ca64 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1316,6 +1316,10 @@ bootstrap@^4.1.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
+bottlejs@^1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/bottlejs/-/bottlejs-1.7.1.tgz#f2673c42feb2ba092d94b8add390e66b3f7d948f"
+
boxen@1.3.0, boxen@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"