mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
add seen apps
This commit is contained in:
parent
b95564f2cf
commit
d2ea5db48c
@ -1,5 +1,6 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import { Grid, Cell, Icon, Switch } from 'react-mdl';
|
import { Grid, Cell, Icon, Switch } from 'react-mdl';
|
||||||
|
import { Link } from 'react-router';
|
||||||
|
|
||||||
import percentLib from 'percent';
|
import percentLib from 'percent';
|
||||||
import Progress from './progress';
|
import Progress from './progress';
|
||||||
@ -7,7 +8,7 @@ import Progress from './progress';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import EditFeatureToggle from './form-edit-container.jsx';
|
import EditFeatureToggle from './form-edit-container.jsx';
|
||||||
import { fetchFeatureToggles, toggleFeature } from '../../store/feature-actions';
|
import { fetchFeatureToggles, toggleFeature } from '../../store/feature-actions';
|
||||||
import { fetchFeatureMetrics } from '../../store/feature-metrics-actions';
|
import { fetchFeatureMetrics, fetchSeenApps } from '../../store/feature-metrics-actions';
|
||||||
|
|
||||||
class EditFeatureToggleWrapper extends React.Component {
|
class EditFeatureToggleWrapper extends React.Component {
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ class EditFeatureToggleWrapper extends React.Component {
|
|||||||
if (this.props.features.length === 0) {
|
if (this.props.features.length === 0) {
|
||||||
this.props.fetchFeatureToggles();
|
this.props.fetchFeatureToggles();
|
||||||
}
|
}
|
||||||
|
this.props.fetchSeenApps();
|
||||||
this.props.fetchFeatureMetrics();
|
this.props.fetchFeatureMetrics();
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
this.props.fetchFeatureMetrics();
|
this.props.fetchFeatureMetrics();
|
||||||
@ -34,14 +36,17 @@ class EditFeatureToggleWrapper extends React.Component {
|
|||||||
toggleFeature,
|
toggleFeature,
|
||||||
features,
|
features,
|
||||||
featureToggleName,
|
featureToggleName,
|
||||||
metrics = {
|
metrics = {},
|
||||||
lastHour: { yes: 0, no: 0, isFallback: true },
|
|
||||||
lastMinute: { yes: 0, no: 0, isFallback: true },
|
|
||||||
},
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const lastHourPercent = 1 * percentLib.calc(metrics.lastHour.yes, metrics.lastHour.yes + metrics.lastHour.no, 0);
|
const {
|
||||||
const lastMinutePercent = 1 * percentLib.calc(metrics.lastMinute.yes, metrics.lastMinute.yes + metrics.lastMinute.no, 0);
|
lastHour = { yes: 0, no: 0, isFallback: true },
|
||||||
|
lastMinute = { yes: 0, no: 0, isFallback: true },
|
||||||
|
seenApps = [],
|
||||||
|
} = metrics;
|
||||||
|
|
||||||
|
const lastHourPercent = 1 * percentLib.calc(lastHour.yes, lastHour.yes + lastHour.no, 0);
|
||||||
|
const lastMinutePercent = 1 * percentLib.calc(lastMinute.yes, lastMinute.yes + lastMinute.no, 0);
|
||||||
|
|
||||||
const featureToggle = features.find(toggle => toggle.name === featureToggleName);
|
const featureToggle = features.find(toggle => toggle.name === featureToggleName);
|
||||||
|
|
||||||
@ -56,38 +61,50 @@ class EditFeatureToggleWrapper extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<h4>{featureToggle.name} <small>{featureToggle.enabled ? 'is enabled' : 'is disabled'}</small></h4>
|
<h4>{featureToggle.name} <small>{featureToggle.enabled ? 'is enabled' : 'is disabled'}</small></h4>
|
||||||
<hr />
|
<hr />
|
||||||
<div style={{ maxWidth: '150px' }} >
|
<div style={{ maxWidth: '200px' }} >
|
||||||
<Switch style={{ cursor: 'pointer' }} onChange={() => toggleFeature(featureToggle)} checked={featureToggle.enabled}>
|
<Switch style={{ cursor: 'pointer' }} onChange={() => toggleFeature(featureToggle)} checked={featureToggle.enabled}>
|
||||||
Toggle {featureToggle.name}
|
Toggle {featureToggle.name}
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<Grid>
|
<Grid style={{ textAlign: 'center' }}>
|
||||||
<Cell col={3} style={{ textAlign: 'center' }}>
|
<Cell col={3}>
|
||||||
{
|
{
|
||||||
metrics.lastMinute.isFallback ?
|
lastMinute.isFallback ?
|
||||||
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }} name="report problem" title="No metrics avaiable" /> :
|
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }} name="report problem" title="No metrics avaiable" /> :
|
||||||
<div>
|
<div>
|
||||||
<Progress strokeWidth={10} percentage={lastMinutePercent} width="50" />
|
<Progress strokeWidth={10} percentage={lastMinutePercent} width="50" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<p><strong>Last minute:</strong> Yes {metrics.lastMinute.yes}, No: {metrics.lastMinute.no}</p>
|
<p><strong>Last minute:</strong> Yes {lastMinute.yes}, No: {lastMinute.no}</p>
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell col={3} style={{ textAlign: 'center' }}>
|
<Cell col={3}>
|
||||||
{
|
{
|
||||||
metrics.lastHour.isFallback ?
|
lastHour.isFallback ?
|
||||||
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }} name="report problem" title="No metrics avaiable" /> :
|
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }} name="report problem" title="No metrics avaiable" /> :
|
||||||
<div>
|
<div>
|
||||||
<Progress strokeWidth={10} percentage={lastHourPercent} width="50" />
|
<Progress strokeWidth={10} percentage={lastHourPercent} width="50" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<p><strong>Last hour:</strong> Yes {metrics.lastHour.yes}, No: {metrics.lastHour.no}</p>
|
<p><strong>Last hour:</strong> Yes {lastHour.yes}, No: {lastHour.no}</p>
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell col={3}>
|
<Cell col={3}>
|
||||||
<p>add apps</p>
|
{seenApps.length > 0 ?
|
||||||
|
(<div><strong>Seen in applications:</strong></div>) :
|
||||||
|
<div>
|
||||||
|
<Icon style={{ width: '100px', height: '100px', fontSize: '100px', color: '#ccc' }} name="report problem" title="Not used in a app in the last hour" />
|
||||||
|
<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>
|
||||||
|
))}
|
||||||
|
<p>add instances count?</p>
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell col={3}>
|
<Cell col={3}>
|
||||||
<p>add instances</p>
|
<p>add history</p>
|
||||||
</Cell>
|
</Cell>
|
||||||
</Grid>
|
</Grid>
|
||||||
<hr />
|
<hr />
|
||||||
@ -102,12 +119,16 @@ function getMetricsForToggle (state, toggleName) {
|
|||||||
if (!toggleName) {
|
if (!toggleName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state.featureMetrics.hasIn(['lastHour', toggleName])) {
|
const result = {};
|
||||||
return {
|
|
||||||
lastHour: state.featureMetrics.getIn(['lastHour', toggleName]),
|
if (state.featureMetrics.hasIn(['seenApps', toggleName])) {
|
||||||
lastMinute: state.featureMetrics.getIn(['lastMinute', toggleName]),
|
result.seenApps = state.featureMetrics.getIn(['seenApps', toggleName]);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (state.featureMetrics.hasIn(['lastHour', toggleName])) {
|
||||||
|
result.lastHour = state.featureMetrics.getIn(['lastHour', toggleName]);
|
||||||
|
result.lastMinute = state.featureMetrics.getIn(['lastMinute', toggleName]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -118,4 +139,5 @@ export default connect((state, props) => ({
|
|||||||
fetchFeatureMetrics,
|
fetchFeatureMetrics,
|
||||||
fetchFeatureToggles,
|
fetchFeatureToggles,
|
||||||
toggleFeature,
|
toggleFeature,
|
||||||
|
fetchSeenApps,
|
||||||
})(EditFeatureToggleWrapper);
|
})(EditFeatureToggleWrapper);
|
||||||
|
@ -8,6 +8,15 @@ function fetchFeatureMetrics () {
|
|||||||
.then(response => response.json());
|
.then(response => response.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const seenURI = '/api/client/seen-apps';
|
||||||
|
|
||||||
|
function fetchSeenApps () {
|
||||||
|
return fetch(seenURI)
|
||||||
|
.then(throwIfNotSuccess)
|
||||||
|
.then(response => response.json());
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
fetchFeatureMetrics,
|
fetchFeatureMetrics,
|
||||||
|
fetchSeenApps,
|
||||||
};
|
};
|
||||||
|
@ -4,10 +4,22 @@ export const START_FETCH_FEATURE_METRICS = 'START_FETCH_FEATURE_METRICS';
|
|||||||
export const RECEIVE_FEATURE_METRICS = 'RECEIVE_FEATURE_METRICS';
|
export const RECEIVE_FEATURE_METRICS = 'RECEIVE_FEATURE_METRICS';
|
||||||
export const ERROR_FETCH_FEATURE_TOGGLES = 'ERROR_FETCH_FEATURE_TOGGLES';
|
export const ERROR_FETCH_FEATURE_TOGGLES = 'ERROR_FETCH_FEATURE_TOGGLES';
|
||||||
|
|
||||||
|
export const START_FETCH_SEEN_APP = 'START_FETCH_SEEN_APP';
|
||||||
|
export const RECEIVE_SEEN_APPS = 'RECEIVE_SEEN_APPS';
|
||||||
|
export const ERROR_FETCH_SEEN_APP = 'ERROR_FETCH_SEEN_APP';
|
||||||
|
|
||||||
function receiveFeatureMetrics (json) {
|
function receiveFeatureMetrics (json) {
|
||||||
return {
|
return {
|
||||||
type: RECEIVE_FEATURE_METRICS,
|
type: RECEIVE_FEATURE_METRICS,
|
||||||
metrics: json,
|
value: json,
|
||||||
|
receivedAt: Date.now(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function receiveSeenApps (json) {
|
||||||
|
return {
|
||||||
|
type: RECEIVE_SEEN_APPS,
|
||||||
|
value: json,
|
||||||
receivedAt: Date.now(),
|
receivedAt: Date.now(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -21,10 +33,21 @@ function dispatchAndThrow (dispatch, type) {
|
|||||||
|
|
||||||
export function fetchFeatureMetrics () {
|
export function fetchFeatureMetrics () {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch({ type: START_FETCH_FEATURE_METRICS });
|
dispatch({ type: START_FETCH_SEEN_APP });
|
||||||
|
|
||||||
return api.fetchFeatureMetrics()
|
return api.fetchFeatureMetrics()
|
||||||
.then(json => dispatch(receiveFeatureMetrics(json)))
|
.then(json => dispatch(receiveFeatureMetrics(json)))
|
||||||
|
.catch(dispatchAndThrow(dispatch, ERROR_FETCH_SEEN_APP));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchSeenApps () {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch({ type: START_FETCH_FEATURE_METRICS });
|
||||||
|
|
||||||
|
return api.fetchSeenApps()
|
||||||
|
.then(json => dispatch(receiveSeenApps(json)))
|
||||||
.catch(dispatchAndThrow(dispatch, ERROR_FETCH_FEATURE_TOGGLES));
|
.catch(dispatchAndThrow(dispatch, ERROR_FETCH_FEATURE_TOGGLES));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,15 +2,19 @@ import { Map as $Map, fromJS } from 'immutable';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
RECEIVE_FEATURE_METRICS,
|
RECEIVE_FEATURE_METRICS,
|
||||||
|
RECEIVE_SEEN_APPS,
|
||||||
} from './feature-metrics-actions';
|
} from './feature-metrics-actions';
|
||||||
|
|
||||||
|
|
||||||
const metrics = (state = fromJS({ lastHour: {}, lastMinute: {} }), action) => {
|
const metrics = (state = fromJS({ lastHour: {}, lastMinute: {}, seenApps: {} }), action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case RECEIVE_SEEN_APPS:
|
||||||
|
console.log('RECEIVE_SEEN_APPS', action.value);
|
||||||
|
return state.set('seenApps', new $Map(action.value));
|
||||||
case RECEIVE_FEATURE_METRICS:
|
case RECEIVE_FEATURE_METRICS:
|
||||||
return state.withMutations((ctx) => {
|
return state.withMutations((ctx) => {
|
||||||
ctx.set('lastHour', new $Map(action.metrics.lastHour));
|
ctx.set('lastHour', new $Map(action.value.lastHour));
|
||||||
ctx.set('lastMinute', new $Map(action.metrics.lastMinute));
|
ctx.set('lastMinute', new $Map(action.value.lastMinute));
|
||||||
return ctx;
|
return ctx;
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user