diff --git a/frontend/src/component/application/application-edit-component.js b/frontend/src/component/application/application-edit-component.js
index 31e63dd682..2c2c73ebcf 100644
--- a/frontend/src/component/application/application-edit-component.js
+++ b/frontend/src/component/application/application-edit-component.js
@@ -1,10 +1,31 @@
-import React, { PureComponent } from 'react';
+/* eslint react/no-multi-comp:off */
+import React, { Component, PureComponent } from 'react';
import { Link } from 'react-router';
-import { Grid, Cell } from 'react-mdl';
+import { Grid, Cell, List, ListItem, ListItemContent, Textfield, Icon } from 'react-mdl';
+
+
+class StatefulTextfield extends Component {
+ constructor (props) {
+ super(props);
+ this.state = { value: props.value };
+ this.setValue = function setValue (e) {
+ this.setState({ value: e.target.value });
+ }.bind(this);
+ }
+
+ render () {
+ return (
+ );
+ }
+}
class ClientStrategies extends PureComponent {
-
componentDidMount () {
this.props.fetchApplication(this.props.appName);
}
@@ -13,44 +34,76 @@ class ClientStrategies extends PureComponent {
if (!this.props.application) {
return
Loading application info...
;
}
+ const {
+ application,
+ storeApplicationMetaData,
+ } = this.props;
const {
appName,
instances,
strategies,
seenToggles,
- } = this.props.application;
+ data = {},
+ } = application;
return (
-
{appName}
+
{appName}
+ {data.description &&
{data.description}
}
-
- Instances
-
- {instances.map(({ instanceId }, i) => - {instanceId}
)}
-
- |
-
- Implemented strategies
-
- {strategies.map((name, i) => (
- -
-
+
+ Toggles
+
+
+ {seenToggles.map((name, i) =>
+
+
+
{name}
- |
- ))}
-
+
+ )}
+
|
-
- Toggles
-
- {seenToggles.map((name, i) => -
-
- {name}
-
-
)}
-
+
+ Implemented strategies
+
+
+ {strategies.map((name, i) => (
+
+
+
+ {name}
+
+
+
+ ))}
+
+ |
+
+ {instances.length} Instances connected
+
+
+ {instances.map(({ instanceId, clientIp, lastSeen }, i) => (
+
+ {clientIp} last seen at {new Date(lastSeen).toLocaleString('nb-NO')}}>
+ {instanceId}
+
+
+ ))}
+
+ |
+
+
+ Edit app meta data
+ |
+
+ storeApplicationMetaData(appName, 'url', e.target.value)} />
+ storeApplicationMetaData(appName, 'description', e.target.value)} />
+ |
+
+ storeApplicationMetaData(appName, 'icon', e.target.value)} />
+ storeApplicationMetaData(appName, 'color', e.target.value)} />
|
|
diff --git a/frontend/src/component/application/application-edit-container.js b/frontend/src/component/application/application-edit-container.js
index fa76680372..b3b2d66989 100644
--- a/frontend/src/component/application/application-edit-container.js
+++ b/frontend/src/component/application/application-edit-container.js
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import ApplicationEdit from './application-edit-component';
-import { fetchApplication } from '../../store/application/actions';
+import { fetchApplication, storeApplicationMetaData } from '../../store/application/actions';
const mapStateToProps = (state, props) => {
let application = state.applications.getIn(['apps', props.appName]);
@@ -12,6 +12,9 @@ const mapStateToProps = (state, props) => {
};
};
-const Constainer = connect(mapStateToProps, { fetchApplication })(ApplicationEdit);
+const Constainer = connect(mapStateToProps, {
+ fetchApplication,
+ storeApplicationMetaData,
+})(ApplicationEdit);
export default Constainer;
diff --git a/frontend/src/component/application/application-list-component.js b/frontend/src/component/application/application-list-component.js
index 8d616d3568..f96e3fc63b 100644
--- a/frontend/src/component/application/application-list-component.js
+++ b/frontend/src/component/application/application-list-component.js
@@ -1,4 +1,5 @@
import React, { Component } from 'react';
+import { List, ListItem, ListItemContent } from 'react-mdl';
import { Link } from 'react-router';
class ClientStrategies extends Component {
@@ -17,15 +18,19 @@ class ClientStrategies extends Component {
}
return (
-
- {applications.map(item => (
- -
-
- Link: {item.appName}
-
-
+ Applications
+
+
+ {applications.map(({ appName, data = {} }) => (
+
+
+
+ {appName}
+
+
+
))}
-
+
);
}
diff --git a/frontend/src/component/feature/view-edit-container.jsx b/frontend/src/component/feature/view-edit-container.jsx
index 98a662e2ac..84f6469a98 100644
--- a/frontend/src/component/feature/view-edit-container.jsx
+++ b/frontend/src/component/feature/view-edit-container.jsx
@@ -105,17 +105,22 @@ class EditFeatureToggleWrapper extends React.Component {
Not used in a app in the last hour. This might be due to your client implementation is not reporting usage.
}
- {seenApps.length > 0 && seenApps.map((appName) => (
-
- {appName}
-
+
+ {seenApps.length > 0 && seenApps.map(({ appName, data = {} }) => (
+
+
+
+ {appName}
+
+
+
))}
- add instances count?
+
History
- {history.map(({ createdAt, type, createdBy }, i) =>
+ {history.map(({ createdAt, type, createdBy }, i) =>
{createdBy}
diff --git a/frontend/src/data/applications-api.js b/frontend/src/data/applications-api.js
index fcbd5c4ae3..3b72645b2a 100644
--- a/frontend/src/data/applications-api.js
+++ b/frontend/src/data/applications-api.js
@@ -20,8 +20,20 @@ function fetchApplicationsWithStrategyName (strategyName) {
.then(response => response.json());
}
+function storeApplicationMetaData (appName, key, value) {
+ const data = {};
+ data[key] = value;
+ return fetch(`${URI}/${appName}`, {
+ method: 'POST',
+ headers,
+ body: JSON.stringify(data),
+ credentials: 'include',
+ }).then(throwIfNotSuccess);
+}
+
module.exports = {
fetchApplication,
fetchAll,
fetchApplicationsWithStrategyName,
+ storeApplicationMetaData,
};
diff --git a/frontend/src/store/application/actions.js b/frontend/src/store/application/actions.js
index 311c5d6b10..3f295bd4c3 100644
--- a/frontend/src/store/application/actions.js
+++ b/frontend/src/store/application/actions.js
@@ -2,6 +2,7 @@ import api from '../../data/applications-api';
export const RECEIVE_ALL_APPLICATIONS = 'RECEIVE_ALL_APPLICATIONS';
export const ERROR_RECEIVE_ALL_APPLICATIONS = 'ERROR_RECEIVE_ALL_APPLICATIONS';
+export const ERROR_UPDATING_APPLICATION_DATA = 'ERROR_UPDATING_APPLICATION_DATA';
export const RECEIVE_APPLICATION = 'RECEIVE_APPLICATION';
@@ -15,8 +16,8 @@ const recieveApplication = (json) => ({
value: json,
});
-const errorReceiveApplications = (statusCode) => ({
- type: ERROR_RECEIVE_ALL_APPLICATIONS,
+const errorReceiveApplications = (statusCode, type = ERROR_RECEIVE_ALL_APPLICATIONS) => ({
+ type,
statusCode,
});
@@ -26,6 +27,11 @@ export function fetchAll () {
.catch(error => dispatch(errorReceiveApplications(error)));
}
+export function storeApplicationMetaData (appName, key, value) {
+ return dispatch => api.storeApplicationMetaData(appName, key, value)
+ .catch(error => dispatch(errorReceiveApplications(error, ERROR_UPDATING_APPLICATION_DATA)));
+}
+
export function fetchApplication (appName) {
return dispatch => api.fetchApplication(appName)
.then(json => dispatch(recieveApplication(json)))
|