1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00

applications

This commit is contained in:
sveisvei 2016-12-09 14:02:36 +01:00
parent 4c343adb34
commit 946f9af733
6 changed files with 131 additions and 47 deletions

View File

@ -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 (<Textfield label={this.props.label}
floatingLabel
rows={this.props.rows}
value={this.state.value}
onChange={this.setValue}
onBlur={this.props.onBlur} />
);
}
}
class ClientStrategies extends PureComponent {
componentDidMount () {
this.props.fetchApplication(this.props.appName);
}
@ -13,44 +34,76 @@ class ClientStrategies extends PureComponent {
if (!this.props.application) {
return <div>Loading application info...</div>;
}
const {
application,
storeApplicationMetaData,
} = this.props;
const {
appName,
instances,
strategies,
seenToggles,
} = this.props.application;
data = {},
} = application;
return (
<div>
<h5>{appName}</h5>
<h5><Icon name={data.icon || 'apps'} /> {appName}</h5>
{data.description && <p>{data.description} </p>}
<Grid>
<Cell col={4}>
<h6>Instances</h6>
<ol className="demo-list-item mdl-list">
{instances.map(({ instanceId }, i) => <li className="mdl-list__item" key={i}>{instanceId}</li>)}
</ol>
</Cell>
<Cell col={4}>
<h6>Implemented strategies</h6>
<ol className="demo-list-item mdl-list">
{strategies.map((name, i) => (
<li className="mdl-list__item" key={`${name}-${i}`}>
<Link to={`/strategies/view/${name}`}>
<Cell col={3}>
<h6> Toggles</h6>
<hr />
<List>
{seenToggles.map((name, i) =>
<ListItem key={i}>
<ListItemContent icon="check box">
<Link to={`/features/edit/${name}`}>
{name}
</Link>
</li>
))}
</ol>
</ListItemContent>
</ListItem>)}
</List>
</Cell>
<Cell col={4}>
<h6>Toggles</h6>
<ol className="demo-list-item mdl-list">
{seenToggles.map((name, i) => <li className="mdl-list__item" key={i}>
<Link to={`/features/edit/${name}`}>
{name}
</Link>
</li>)}
</ol>
<Cell col={3}>
<h6>Implemented strategies</h6>
<hr />
<List>
{strategies.map((name, i) => (
<ListItem key={`${name}-${i}`}>
<ListItemContent icon="toc">
<Link to={`/strategies/view/${name}`}>
{name}
</Link>
</ListItemContent>
</ListItem>
))}
</List>
</Cell>
<Cell col={6}>
<h6>{instances.length} Instances connected</h6>
<hr />
<List>
{instances.map(({ instanceId, clientIp, lastSeen }, i) => (
<ListItem key={i} twoLine>
<ListItemContent icon="timeline" subtitle={<span>{clientIp} last seen at <small>{new Date(lastSeen).toLocaleString('nb-NO')}</small></span>}>
{instanceId}
</ListItemContent>
</ListItem>
))}
</List>
</Cell>
<Cell col={12}>
<h5>Edit app meta data</h5>
</Cell>
<Cell col={6}>
<StatefulTextfield value={data.url} label="URL" onBlur={(e) => storeApplicationMetaData(appName, 'url', e.target.value)} /><br />
<StatefulTextfield value={data.description} label="Description" rows={5} onBlur={(e) => storeApplicationMetaData(appName, 'description', e.target.value)} />
</Cell>
<Cell col={6}>
<StatefulTextfield value={data.icon} label="Select icon" onBlur={(e) => storeApplicationMetaData(appName, 'icon', e.target.value)} />
<StatefulTextfield value={data.color} label="Select color" onBlur={(e) => storeApplicationMetaData(appName, 'color', e.target.value)} />
</Cell>
</Grid>
</div>

View File

@ -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;

View File

@ -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 (
<div>
<ul>
{applications.map(item => (
<li>
<Link key={item.appName} to={`/applications/${item.appName}`}>
Link: {item.appName}
</Link>
</li>
<h5>Applications</h5>
<hr />
<List>
{applications.map(({ appName, data = {} }) => (
<ListItem key={appName} twoLine>
<ListItemContent avatar={data.icon || 'apps'} subtitle={data.description}>
<Link to={`/applications/${appName}`}>
{appName}
</Link>
</ListItemContent>
</ListItem>
))}
</ul>
</List>
</div>
);
}

View File

@ -105,17 +105,22 @@ class EditFeatureToggleWrapper extends React.Component {
<div><small><strong>Not used in a app in the last hour.</strong> This might be due to your client implementation is not reporting usage.</small></div>
</div>
}
{seenApps.length > 0 && seenApps.map((appName) => (
<Link key={appName} to={`/applications/${appName}`}>
{appName}
</Link>
<List style={{ textAlign: 'left' }}>
{seenApps.length > 0 && seenApps.map(({ appName, data = {} }) => (
<ListItem twoLine>
<ListItemContent avatar={data.icon || 'apps'} subtitle={data.description || '-'}>
<Link key={appName} to={`/applications/${appName}`}>
{appName}
</Link>
</ListItemContent>
</ListItem>
))}
<p>add instances count?</p>
</List>
</Cell>
<Cell col={3}>
<div><strong>History</strong></div>
<List style={{ textAlign: 'left' }}>
{history.map(({ createdAt, type, createdBy }, i) =>
{history.map(({ createdAt, type, createdBy }, i) =>
<ListItem twoLine key={i}>
<ListItemContent title={type} avatar={getIcon(type)} subtitle={createdAt}>
{createdBy}

View File

@ -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,
};

View File

@ -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)))