diff --git a/frontend/locales/en-us.json b/frontend/locales/en-us.json
index b74f12f2..46f06db4 100644
--- a/frontend/locales/en-us.json
+++ b/frontend/locales/en-us.json
@@ -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"
}
}
diff --git a/frontend/src/components/create-monitor/index.js b/frontend/src/components/create-monitor/index.js
new file mode 100644
index 00000000..43637046
--- /dev/null
+++ b/frontend/src/components/create-monitor/index.js
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/components/manage-monitor/index.js b/frontend/src/components/manage-monitor/index.js
new file mode 100644
index 00000000..c61bbf54
--- /dev/null
+++ b/frontend/src/components/manage-monitor/index.js
@@ -0,0 +1,5 @@
+const React = require('react');
+
+module.exports = () => (
+ manage monitor
+);
\ No newline at end of file
diff --git a/frontend/src/components/monitors/index.js b/frontend/src/components/monitors/index.js
new file mode 100644
index 00000000..ae60ceee
--- /dev/null
+++ b/frontend/src/components/monitors/index.js
@@ -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: () => (
+
+ ),
+ manage: () => (
+
+ )
+ };
+
+ const links = ['create', 'manage'].map((name) => {
+ const id = `monitors.${name}`;
+ const className = page === name ? 'active' : '';
+ const onClick = (ev) => togglePage(name);
+ const href = `#${name}`;
+
+ return (
+
+
+
+
+
+ );
+ });
+
+ return (
+
+
+
+
+
+ for {metricType.name}
+
+
+
+ {views[page]()}
+
+
+
+ );
+};
+
+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;
diff --git a/frontend/src/containers/metrics/add-metrics.js b/frontend/src/containers/metrics/add-metrics.js
index c1091361..adc9728f 100644
--- a/frontend/src/containers/metrics/add-metrics.js
+++ b/frontend/src/containers/metrics/add-metrics.js
@@ -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,
};
diff --git a/frontend/src/containers/metrics/index.js b/frontend/src/containers/metrics/index.js
index e69de29b..2e42b111 100644
--- a/frontend/src/containers/metrics/index.js
+++ b/frontend/src/containers/metrics/index.js
@@ -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 (
+
+ );
+};
+
+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);
diff --git a/frontend/src/containers/metrics/monitors.js b/frontend/src/containers/metrics/monitors.js
new file mode 100644
index 00000000..4e196513
--- /dev/null
+++ b/frontend/src/containers/metrics/monitors.js
@@ -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);
diff --git a/frontend/src/containers/service/metrics.js b/frontend/src/containers/service/metrics.js
index c7ffa76e..c179be15 100644
--- a/frontend/src/containers/service/metrics.js
+++ b/frontend/src/containers/service/metrics.js
@@ -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 (
-
- );
-};
-
-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);
diff --git a/frontend/src/mock-state.json b/frontend/src/mock-state.json
index 70fa0434..937c0396 100644
--- a/frontend/src/mock-state.json
+++ b/frontend/src/mock-state.json
@@ -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",
diff --git a/frontend/src/prop-types.js b/frontend/src/prop-types.js
index 9908426d..f7baee89 100644
--- a/frontend/src/prop-types.js
+++ b/frontend/src/prop-types.js
@@ -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
};
diff --git a/frontend/src/state/actions.js b/frontend/src/state/actions.js
index e0811e7c..7e5262ed 100644
--- a/frontend/src/state/actions.js
+++ b/frontend/src/state/actions.js
@@ -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`)
};
diff --git a/frontend/src/state/reducers/index.js b/frontend/src/state/reducers/index.js
index 9f428409..c87158f0 100644
--- a/frontend/src/state/reducers/index.js
+++ b/frontend/src/state/reducers/index.js
@@ -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')
diff --git a/frontend/src/state/reducers/monitors.js b/frontend/src/state/reducers/monitors.js
new file mode 100644
index 00000000..1c8a8204
--- /dev/null
+++ b/frontend/src/state/reducers/monitors.js
@@ -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
+ }
+ })
+}, {});
diff --git a/frontend/src/state/selectors.js b/frontend/src/state/selectors.js
index 7c154b3d..23a06af4 100644
--- a/frontend/src/state/selectors.js
+++ b/frontend/src/state/selectors.js
@@ -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
};