create monitor modal

This commit is contained in:
Sérgio Ramos 2017-01-16 19:45:15 +00:00
parent 7e157a15a1
commit c378d8309a
14 changed files with 458 additions and 55 deletions

View File

@ -37,5 +37,21 @@
"title": "Apache HTTP requests",
"description": "Number of website requests to apache if it is used."
}
},
"monitors": {
"conditions": "Conditions",
"conditions-subtitle": "Please define what changes you wish to be alerted of.",
"if": "If metric is",
"above": "Above",
"equal": "Equal",
"below": "Below",
"average": "on averga",
"during": "during",
"last5": "last 5 minutes",
"notification": "Notification",
"notification-subtitle": "Type in users or teams who you wish to be alerted.",
"submit": "Create",
"create": "Create monitor",
"manage": "Managing monitors"
}
}

View File

@ -0,0 +1,125 @@
const React = require('react');
const ReactIntl = require('react-intl');
const Styled = require('styled-components');
const Button = require('@ui/components/button');
const Column = require('@ui/components/column');
const Input = require('@ui/components/input');
const fns = require('@ui/shared/functions');
const Row = require('@ui/components/row');
const Select = require('@ui/components/select');
const {
FormattedMessage
} = ReactIntl;
const {
default: styled
} = Styled;
const {
remcalc
} = fns;
const H4 = styled.h4`
margin-bottom: ${remcalc(5)} !important;
`;
const P = styled.p`
margin-bottom: ${remcalc(20)} !important;
`;
const ConditionsRow = styled(Row)`
margin-bottom: ${remcalc(33)};
`;
const TextColumn = styled(Column)`
display: flex;
flex-direction: column;
justify-content: center;
`;
const Text = styled.p`
margin: 0 auto !important;
`;
const RightText = styled(Text)`
margin: 0 0 0 auto !important;
`;
const PeopleInput = styled(Input)`
margin-bottom: ${remcalc(24)} !important;
`;
module.exports = () => {
return (
<div>
<H4>
<FormattedMessage id='monitors.conditions' />
</H4>
<P>
<FormattedMessage id='monitors.conditions-subtitle' />
</P>
<ConditionsRow around>
<TextColumn md={2} xs={12}>
<RightText>
<FormattedMessage id='monitors.if' />
</RightText>
</TextColumn>
<Column md={2} xs={12}>
<Select>
<option>
<FormattedMessage id='monitors.above' />
</option>
<option>
<FormattedMessage id='monitors.equal' />
</option>
<option>
<FormattedMessage id='monitors.below' />
</option>
</Select>
</Column>
<Column md={2} xs={12}>
<Input placeholder='value' />
</Column>
<Column md={2} xs={12}>
<Select>
<option>
<FormattedMessage id='monitors.average' />
</option>
</Select>
</Column>
<TextColumn md={1}xs={12}>
<Text>
<FormattedMessage id='monitors.during' />
</Text>
</TextColumn>
<Column md={3} xs={12}>
<Select>
<option>
<FormattedMessage id='monitors.last5' />
</option>
</Select>
</Column>
</ConditionsRow>
<H4>
<FormattedMessage id='monitors.notification' />
</H4>
<P>
<FormattedMessage id='monitors.notification-subtitle' />
</P>
<Row>
<Column xs={12}>
<PeopleInput />
</Column>
</Row>
<Row>
<Column xs={12}>
<Button>
<FormattedMessage id='monitors.submit' />
</Button>
</Column>
</Row>
</div>
);
};

View File

@ -0,0 +1,5 @@
const React = require('react');
module.exports = () => (
<p>manage monitor</p>
);

View File

@ -0,0 +1,130 @@
const React = require('react');
const ReactIntl = require('react-intl');
const Styled = require('styled-components');
const constants = require('@ui/shared/constants');
const Close = require('@ui/components/close');
const CreateMonitor = require('@components/create-monitor');
const fns = require('@ui/shared/functions');
const Li = require('@ui/components/horizontal-list/li');
const ManageMonitor = require('@components/manage-monitor');
const Modal = require('@ui/components/modal');
const PropTypes = require('@root/prop-types');
const Ul = require('@ui/components/horizontal-list/ul');
const {
FormattedMessage
} = ReactIntl;
const {
default: styled
} = Styled;
const {
colors
} = constants;
const {
remcalc
} = fns;
const H1 = styled.h1`
font-size: ${remcalc(26)} !important;
font-weight: 600;
font-style: normal;
font-stretch: normal;
color: ${colors.brandSecondaryColor};
margin: ${remcalc(24)} auto ${remcalc(9)} ${remcalc(24)} !important;
`;
const H3 = styled.h3`
font-size: ${remcalc(16)} !important;
font-weight: 600;
font-style: normal;
font-stretch: normal;
color: ${colors.brandSecondaryColor};
margin: ${remcalc(0)} auto ${remcalc(26)} ${remcalc(24)} !important;
`;
const Header = styled.header`
overflow: hidden;
background: ${colors.brandPrimaryColor};
border-bottom: solid ${remcalc(1)} ${colors.borderSecondary};
`;
const StyledModal = styled(Modal)`
background: ${colors.brandInactive} !important;
box-shadow: 0 ${remcalc(2)} 0 0 rgba(0, 0, 0, 0.05);
padding: 0 !important;
`;
const View = styled.div`
margin: ${remcalc(18)} ${remcalc(24)} ${remcalc(49)} ${remcalc(24)};
height: 100%;
`;
const Monitors = ({
active = false,
handleDismiss = () => null,
metricType = {},
page = 'create',
submit = () => null,
togglePage = () => null
}) => {
const views = {
create: () => (
<CreateMonitor submit={submit} />
),
manage: () => (
<ManageMonitor />
)
};
const links = ['create', 'manage'].map((name) => {
const id = `monitors.${name}`;
const className = page === name ? 'active' : '';
const onClick = (ev) => togglePage(name);
const href = `#${name}`;
return (
<Li key={name}>
<a
className={className}
href={href}
onClick={onClick}
>
<FormattedMessage id={id} />
</a>
</Li>
);
});
return (
<StyledModal active={!!active} onDismiss={handleDismiss}>
<Header>
<H1>
<FormattedMessage id='settings' />
</H1>
<H3>for {metricType.name}</H3>
</Header>
<View>
<Ul>
{links}
</Ul>
{views[page]()}
</View>
<Close onClick={handleDismiss} />
</StyledModal>
);
};
Monitors.propTypes = {
active: React.PropTypes.string,
handleDismiss: React.PropTypes.func.isRequired,
metricType: PropTypes.metricType,
page: React.PropTypes.string,
submit: React.PropTypes.func.isRequired,
togglePage: React.PropTypes.func.isRequired
};
module.exports = Monitors;

View File

@ -57,7 +57,7 @@ const AddMetrics = ({
};
AddMetrics.propTypes = {
metricTypes: PropTypes.metricTypes.isRequired,
metricTypes: React.PropTypes.arrayOf(React.PropTypes.string),
metrics: React.PropTypes.arrayOf(PropTypes.metric).isRequired,
onAddMetric: React.PropTypes.func.isRequired,
};

View File

@ -0,0 +1,70 @@
const React = require('react');
const ReactRedux = require('react-redux');
const actions = require('@state/actions');
const AddMetrics = require('./add-metrics');
const Button = require('@ui/components/button');
const Column = require('@ui/components/column');
const Monitors = require('./monitors');
const PropTypes = require('@root/prop-types');
const Row = require('@ui/components/row');
const {
connect
} = ReactRedux;
const {
toggleMonitorView
} = actions;
const Metrics = ({
addMetric,
metrics,
metricTypes,
metricTypeUuid = '',
service,
toggleMonitorView = () => null
}) => {
const onMonitorsClick = (ev) => toggleMonitorView(metricTypeUuid);
return (
<div>
<Row reverse>
<Column>
<Button onClick={onMonitorsClick}>Monitors</Button>
</Column>
</Row>
<Monitors />
<AddMetrics
metricTypes={metricTypes}
metrics={metrics}
onAddMetric={addMetric}
/>
</div>
);
};
Metrics.propTypes = {
addMetric: React.PropTypes.func.isRequired,
metricTypeUuid: React.PropTypes.string,
metricTypes: React.PropTypes.arrayOf(React.PropTypes.string),
metrics: React.PropTypes.arrayOf(PropTypes.metric),
service: PropTypes.service,
toggleMonitorView: React.PropTypes.func.isRequired
};
const mapStateToProps = (state) => ({
// hardcoded now, but should be dynamic
// actually, the use for this prop is going to disapear
metricTypeUuid: 'dca08514-72e5-46ce-ad91-e68b3b0914d4',
});
const mapDispatchToProps = (dispatch) => ({
toggleMonitorView: (metricTypeUuid) =>
dispatch(toggleMonitorView(metricTypeUuid))
});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(Metrics);

View File

@ -0,0 +1,36 @@
const ReactRedux = require('react-redux');
const actions = require('@state/actions');
const Monitors = require('@components/monitors');
const selectors = require('@state/selectors');
const {
connect
} = ReactRedux;
const {
metricTypeByUuidSelector
} = selectors;
const {
toggleMonitorView,
switchMonitorViewPage,
createMonitor
} = actions;
const mapStateToProps = (state) => ({
metricType: metricTypeByUuidSelector(state.monitors.ui.active)(state),
active: state.monitors.ui.active,
page: state.monitors.ui.page
});
const mapDispatchToProps = (dispatch) => ({
handleDismiss: () => dispatch(toggleMonitorView()),
togglePage: (newPage) => dispatch(switchMonitorViewPage(newPage)),
submit: (meta) => dispatch(createMonitor(meta))
});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(Monitors);

View File

@ -1,9 +1,8 @@
const React = require('react');
const ReactRedux = require('react-redux');
const PropTypes = require('@root/prop-types');
const selectors = require('@state/selectors');
const AddMetrics = require('../metrics/add-metrics');
const actions = require('@state/actions');
const Metrics = require('@containers/metrics');
const selectors = require('@state/selectors');
const {
connect
@ -18,41 +17,6 @@ const {
addMetric
} = actions;
const Metrics = ({
addMetric,
metrics,
metricTypes,
service
}) => {
const onAddMetric = (metric) => {
addMetric({
id: metric,
service: service.uuid
});
};
return (
<div>
<p>metrics</p>
<div>
<AddMetrics
metricTypes={metricTypes}
metrics={metrics}
onAddMetric={onAddMetric}
/>
</div>
</div>
);
};
Metrics.propTypes = {
addMetric: React.PropTypes.func.isRequired,
metricTypes: PropTypes.metricTypes,
metrics: React.PropTypes.arrayOf(PropTypes.metric),
service: PropTypes.service
};
const mapStateToProps = (state, {
params = {}
}) => ({
@ -62,10 +26,21 @@ const mapStateToProps = (state, {
});
const mapDispatchToProps = (dispatch) => ({
addMetric: (payload) => dispatch(addMetric(payload))
addMetric: (service) => (metric) => dispatch(addMetric({
id: metric,
service: service
}))
});
const mergeProps = (stateProps, dispatchProps, ownProps) => ({
...stateProps,
...dispatchProps,
...ownProps,
addMetric: dispatchProps.addMetric(stateProps.service)
});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
mapDispatchToProps,
mergeProps
)(Metrics);

View File

@ -46,6 +46,12 @@
"location": "Amsterdam, Netherlands"
}]
},
"monitors": {
"ui": {
"active": "dca08514-72e5-46ce-ad91-e68b3b0914d4",
"page": "create"
}
},
"metrics": {
"ui": {
"types": [
@ -68,6 +74,7 @@
"data": {
"types": [{
"uuid": "dca08514-72e5-46ce-ad91-e68b3b0914d4",
"name": "Aggregated CPU usage",
"id": "agg-cpu-usage"
}, {
"uuid": "9e77b50e-42d7-425d-8daf-c0e98e2bdd6a",

View File

@ -39,6 +39,10 @@ const Metric = React.PropTypes.shape({
...BaseObject
});
const MetricType = React.PropTypes.shape({
...BaseObject
});
const Dataset = React.PropTypes.shape({
uuid: React.PropTypes.string,
type: React.PropTypes.string,
@ -57,11 +61,6 @@ const Sections = React.PropTypes.arrayOf(
React.PropTypes.string
);
// consinder renaming this to 'Types' as it could be used for any
const MetricTypes = React.PropTypes.arrayOf(
React.PropTypes.string
);
module.exports = {
account: Account,
link: Link,
@ -71,7 +70,6 @@ module.exports = {
service: Service,
instance: Instance,
metric: Metric,
// consinder renaming this to 'Types' as it could be used for any
metricTypes: MetricTypes,
metricType: MetricType,
dataset: Dataset
};

View File

@ -9,9 +9,12 @@ const APP = constantCase(process.env['APP_NAME']);
module.exports = {
...require('@state/thunks'),
updateRouter: createAction(`${APP}/APP/UPDATE_ROUTER`),
toggleHeaderTooltip: createAction(`${APP}/APP/TOGGLE_HEADER_TOOLTIP`),
toggleServiceCollapsed: createAction(`${APP}/APP/TOGGLE_SERVICE_COLLAPSED`),
addMetric: createAction(`${APP}/APP/ADD_METRIC`),
toggleInstanceCollapsed: createAction(`${APP}/APP/TOGGLE_INSTANCE_COLLAPSED`)
updateRouter: createAction(`${APP}/UPDATE_ROUTER`),
toggleHeaderTooltip: createAction(`${APP}/TOGGLE_HEADER_TOOLTIP`),
toggleServiceCollapsed: createAction(`${APP}/TOGGLE_SERVICE_COLLAPSED`),
addMetric: createAction(`${APP}/ADD_METRIC`),
toggleInstanceCollapsed: createAction(`${APP}/TOGGLE_INSTANCE_COLLAPSED`),
toggleMonitorView: createAction(`${APP}/TOGGLE_MONITOR_VIEW`),
switchMonitorViewPage: createAction(`${APP}/SWITCH_MONITOR_VIEW_PAGE`),
createMonitor: createAction(`${APP}/CREATE_MONITOR`)
};

View File

@ -11,6 +11,7 @@ module.exports = () => {
instances: require('@state/reducers/instances'),
intl: require('@state/reducers/intl'),
metrics: require('@state/reducers/metrics'),
monitors: require('@state/reducers/monitors'),
orgs: require('@state/reducers/orgs'),
projects: require('@state/reducers/projects'),
services: require('@state/reducers/services')

View File

@ -0,0 +1,30 @@
const ReduxActions = require('redux-actions');
const actions = require('@state/actions');
const {
handleActions
} = ReduxActions;
const {
toggleMonitorView,
switchMonitorViewPage
// createMonitor
} = actions;
module.exports = handleActions({
[toggleMonitorView.toString()]: (state, action) => ({
...state,
ui: {
...state.ui,
active: action.payload
}
}),
[switchMonitorViewPage.toString()]: (state, action) => ({
...state,
ui: {
...state.ui,
page: action.payload
}
})
}, {});

View File

@ -93,6 +93,12 @@ const metricsByServiceId = (serviceId) => createSelector(
metricTypes.filter((i) => i.service === service.uuid)
);
const metricTypeByUuid = (metricTypeUuid) => createSelector(
[metricTypes],
(metricTypes) => find(metricTypes, ['uuid', metricTypeUuid])
);
const instancesByProjectId = (projectId) => createSelector(
[instances, projectById(projectId), collapsedInstances, metricDatasets],
(instances, project, collapsed, metrics) =>
@ -119,5 +125,6 @@ module.exports = {
servicesByProjectIdSelector: servicesByProjectId,
instancesByServiceIdSelector: instancesByServiceId,
metricsByServiceIdSelector: metricsByServiceId,
instancesByProjectIdSelector: instancesByProjectId
instancesByProjectIdSelector: instancesByProjectId,
metricTypeByUuidSelector: metricTypeByUuid
};