diff --git a/frontend/src/__mocks__/react-mdl.js b/frontend/src/__mocks__/react-mdl.js
index 2deaebe0e0..04e07f153d 100644
--- a/frontend/src/__mocks__/react-mdl.js
+++ b/frontend/src/__mocks__/react-mdl.js
@@ -17,4 +17,6 @@ module.exports = {
Tabs: 'react-mdl-Tabs',
TableHeader: 'react-mdl-TableHeader',
Textfield: 'react-mdl-Textfield',
+ FooterSection: 'react-mdl-FooterSection',
+ FooterLinkList: 'react-mdl-FooterLinkList',
};
diff --git a/frontend/src/component/api/__tests__/.eslintrc b/frontend/src/component/api/__tests__/.eslintrc
new file mode 100644
index 0000000000..eba2077219
--- /dev/null
+++ b/frontend/src/component/api/__tests__/.eslintrc
@@ -0,0 +1,5 @@
+{
+ "env": {
+ "jest": true
+ }
+}
diff --git a/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap b/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap
new file mode 100644
index 0000000000..3bfed09ff5
--- /dev/null
+++ b/frontend/src/component/api/__tests__/__snapshots__/show-api-details-component-test.jsx.snap
@@ -0,0 +1,51 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly with details 1`] = `
+
+
+
+ GitHub
+
+
+
+ A product by
+
+ FINN.no
+
+
+
+`;
+
+exports[`renders correctly with empty api details 1`] = `
+
+
+
+ GitHub
+
+
+
+ A product by
+
+ FINN.no
+
+
+
+`;
diff --git a/frontend/src/component/api/__tests__/show-api-details-component-test.jsx b/frontend/src/component/api/__tests__/show-api-details-component-test.jsx
new file mode 100644
index 0000000000..c712fff910
--- /dev/null
+++ b/frontend/src/component/api/__tests__/show-api-details-component-test.jsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import ShowApiDetailsComponent from '../show-api-details-component';
+import renderer from 'react-test-renderer';
+
+jest.mock('react-mdl');
+
+test('renders correctly with empty api details', () => {
+ const tree = renderer.create().toJSON();
+ expect(tree).toMatchSnapshot();
+});
+
+test('renders correctly with details', () => {
+ const tree = renderer
+ .create()
+ .toJSON();
+ expect(tree).toMatchSnapshot();
+});
diff --git a/frontend/src/component/api/show-api-details-component.jsx b/frontend/src/component/api/show-api-details-component.jsx
new file mode 100644
index 0000000000..c0c83a42ec
--- /dev/null
+++ b/frontend/src/component/api/show-api-details-component.jsx
@@ -0,0 +1,32 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { FooterSection, FooterLinkList } from 'react-mdl';
+
+class ShowApiDetailsComponent extends Component {
+ static propTypes = {
+ apiDetails: PropTypes.object.isRequired,
+ fetchAll: PropTypes.func.isRequired,
+ };
+
+ componentDidMount() {
+ this.props.fetchAll();
+ }
+
+ render() {
+ const version = this.props.apiDetails.version || '';
+ return (
+
+
+
+ GitHub
+
+
+ A product by FINN.no
+
+
+
+ );
+ }
+}
+
+export default ShowApiDetailsComponent;
diff --git a/frontend/src/component/api/show-api-details-container.jsx b/frontend/src/component/api/show-api-details-container.jsx
new file mode 100644
index 0000000000..fccb7319ef
--- /dev/null
+++ b/frontend/src/component/api/show-api-details-container.jsx
@@ -0,0 +1,13 @@
+import { connect } from 'react-redux';
+import ShowApiDetailsComponent from './show-api-details-component';
+import { fetchAll } from '../../store/api/actions';
+
+const mapDispatchToProps = {
+ fetchAll,
+};
+
+const mapStateToProps = state => ({
+ apiDetails: state.api.toJS(),
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(ShowApiDetailsComponent);
diff --git a/frontend/src/component/app.jsx b/frontend/src/component/app.jsx
index f252587ff8..a573d253d2 100644
--- a/frontend/src/component/app.jsx
+++ b/frontend/src/component/app.jsx
@@ -20,6 +20,7 @@ import ErrorContainer from './error/error-container';
import UserContainer from './user/user-container';
import ShowUserContainer from './user/show-user-container';
+import ShowApiDetailsContainer from './api/show-api-details-container';
import { ScrollContainer } from 'react-router-scroll';
function replace(input, params) {
@@ -193,16 +194,7 @@ export default class App extends Component {
-
-
-
- GitHub
-
-
- A product by FINN.no
-
-
-
+
diff --git a/frontend/src/data/api.js b/frontend/src/data/api.js
new file mode 100644
index 0000000000..e584f14407
--- /dev/null
+++ b/frontend/src/data/api.js
@@ -0,0 +1,13 @@
+import { throwIfNotSuccess, headers } from './helper';
+
+const URI = 'api';
+
+function fetchAll() {
+ return fetch(URI, { headers, credentials: 'include' })
+ .then(throwIfNotSuccess)
+ .then(response => response.json());
+}
+
+export default {
+ fetchAll,
+};
diff --git a/frontend/src/store/api/__tests__/.eslintrc b/frontend/src/store/api/__tests__/.eslintrc
new file mode 100644
index 0000000000..eba2077219
--- /dev/null
+++ b/frontend/src/store/api/__tests__/.eslintrc
@@ -0,0 +1,5 @@
+{
+ "env": {
+ "jest": true
+ }
+}
diff --git a/frontend/src/store/api/__tests__/api-store-tests.js b/frontend/src/store/api/__tests__/api-store-tests.js
new file mode 100644
index 0000000000..93140f8d2d
--- /dev/null
+++ b/frontend/src/store/api/__tests__/api-store-tests.js
@@ -0,0 +1,18 @@
+import apiReducer from '../index';
+import { RECIEVE_API_DETAILS } from '../actions';
+
+test('should have inital state', () => {
+ const store = apiReducer(undefined, {});
+ expect(store.toJS()).toEqual({});
+});
+
+test('should have new state', () => {
+ const store = apiReducer(undefined, { type: RECIEVE_API_DETAILS, value: { version: '1.1.1' } });
+ expect(store.toJS()).toEqual({ version: '1.1.1' });
+});
+
+test('should have updated state', () => {
+ const inital = apiReducer(undefined, { type: RECIEVE_API_DETAILS, value: { version: '1.1.1' } });
+ const store = apiReducer(inital, { type: RECIEVE_API_DETAILS, value: { version: '1.2.1' } });
+ expect(store.toJS()).toEqual({ version: '1.2.1' });
+});
diff --git a/frontend/src/store/api/actions.js b/frontend/src/store/api/actions.js
new file mode 100644
index 0000000000..a8ef51b855
--- /dev/null
+++ b/frontend/src/store/api/actions.js
@@ -0,0 +1,24 @@
+import api from '../../data/api';
+
+export const RECIEVE_API_DETAILS = 'RECIEVE_API_DETAILS';
+export const ERROR_RECIEVE_API_DETAILS = 'ERROR_RECIEVE_API_DETAILS';
+
+export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION';
+
+const recieveApiDetails = json => ({
+ type: RECIEVE_API_DETAILS,
+ value: json,
+});
+
+const errorRecieveApiDetails = (statusCode, type = ERROR_RECIEVE_API_DETAILS) => ({
+ type,
+ statusCode,
+});
+
+export function fetchAll() {
+ return dispatch =>
+ api
+ .fetchAll()
+ .then(json => dispatch(recieveApiDetails(json)))
+ .catch(error => dispatch(errorRecieveApiDetails(error)));
+}
diff --git a/frontend/src/store/api/index.js b/frontend/src/store/api/index.js
new file mode 100644
index 0000000000..756b8b4688
--- /dev/null
+++ b/frontend/src/store/api/index.js
@@ -0,0 +1,14 @@
+import { Map } from 'immutable';
+import { RECIEVE_API_DETAILS } from './actions';
+
+const store = (state = new Map(), action) => {
+ switch (action.type) {
+ case RECIEVE_API_DETAILS:
+ state = new Map(action.value);
+ return state;
+ default:
+ return state;
+ }
+};
+
+export default store;
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
index 0ca4a4b88f..278cea3ab9 100644
--- a/frontend/src/store/index.js
+++ b/frontend/src/store/index.js
@@ -9,6 +9,7 @@ import error from './error-store';
import clientInstances from './client-instance-store';
import settings from './settings';
import user from './user';
+import api from './api';
import applications from './application';
const unleashStore = combineReducers({
@@ -23,6 +24,7 @@ const unleashStore = combineReducers({
settings,
user,
applications,
+ api,
});
export default unleashStore;