diff --git a/frontend/app/components/Alerts/AlertForm.js b/frontend/app/components/Alerts/AlertForm.js
index 1701c8e0a..f5e4ee236 100644
--- a/frontend/app/components/Alerts/AlertForm.js
+++ b/frontend/app/components/Alerts/AlertForm.js
@@ -1,4 +1,4 @@
-import React, { useEffect } from 'react'
+import React, { useEffect } from 'react';
import { Button, Form, Input, SegmentSelection, Checkbox, Message, Link, Icon } from 'UI';
import { alertMetrics as metrics } from 'App/constants';
import { alertConditions as conditions } from 'App/constants';
@@ -9,333 +9,322 @@ import DropdownChips from './DropdownChips';
import { validateEmail } from 'App/validate';
import cn from 'classnames';
import { fetchTriggerOptions } from 'Duck/alerts';
-import Select from 'Shared/Select'
+import Select from 'Shared/Select';
const thresholdOptions = [
- { label: '15 minutes', value: 15 },
- { label: '30 minutes', value: 30 },
- { label: '1 hour', value: 60 },
- { label: '2 hours', value: 120 },
- { label: '4 hours', value: 240 },
- { label: '1 day', value: 1440 },
+ { label: '15 minutes', value: 15 },
+ { label: '30 minutes', value: 30 },
+ { label: '1 hour', value: 60 },
+ { label: '2 hours', value: 120 },
+ { label: '4 hours', value: 240 },
+ { label: '1 day', value: 1440 },
];
const changeOptions = [
- { label: 'change', value: 'change' },
- { label: '% change', value: 'percent' },
+ { label: 'change', value: 'change' },
+ { label: '% change', value: 'percent' },
];
-const Circle = ({ text }) => (
-
{text}
-)
+const Circle = ({ text }) => {text}
;
const Section = ({ index, title, description, content }) => (
-
-
-
-
-
{title}
- { description &&
{description}
}
-
-
+
+
+
+
+
{title}
+ {description &&
{description}
}
+
+
-
-
-)
+);
const integrationsRoute = client(CLIENT_TABS.INTEGRATIONS);
-const AlertForm = props => {
- const { instance, slackChannels, webhooks, loading, onDelete, deleting, triggerOptions, metricId, style={ width: '580px', height: '100vh' } } = props;
- const write = ({ target: { value, name } }) => props.edit({ [ name ]: value })
- const writeOption = (e, { name, value }) => props.edit({ [ name ]: value.value });
- const onChangeCheck = ({ target: { checked, name }}) => props.edit({ [ name ]: checked })
- // const onChangeOption = ({ checked, name }) => props.edit({ [ name ]: checked })
- // const onChangeCheck = (e) => { console.log(e) }
+const AlertForm = (props) => {
+ const {
+ instance,
+ slackChannels,
+ webhooks,
+ loading,
+ onDelete,
+ deleting,
+ triggerOptions,
+ metricId,
+ style = { width: '580px', height: '100vh' },
+ } = props;
+ const write = ({ target: { value, name } }) => props.edit({ [name]: value });
+ const writeOption = (e, { name, value }) => props.edit({ [name]: value.value });
+ const onChangeCheck = ({ target: { checked, name } }) => props.edit({ [name]: checked });
+ // const onChangeOption = ({ checked, name }) => props.edit({ [ name ]: checked })
+ // const onChangeCheck = (e) => { console.log(e) }
- useEffect(() => {
- props.fetchTriggerOptions();
- }, [])
+ useEffect(() => {
+ props.fetchTriggerOptions();
+ }, []);
- const writeQueryOption = (e, { name, value }) => {
- const { query } = instance;
- props.edit({ query: { ...query, [name] : value } });
- }
+ const writeQueryOption = (e, { name, value }) => {
+ const { query } = instance;
+ props.edit({ query: { ...query, [name]: value } });
+ };
- const writeQuery = ({ target: { value, name } }) => {
- const { query } = instance;
- props.edit({ query: { ...query, [name] : value } });
- }
+ const writeQuery = ({ target: { value, name } }) => {
+ const { query } = instance;
+ props.edit({ query: { ...query, [name]: value } });
+ };
- const metric = (instance && instance.query.left) ? triggerOptions.find(i => i.value === instance.query.left) : null;
- const unit = metric ? metric.unit : '';
- const isThreshold = instance.detectionMethod === 'threshold';
+ const metric = instance && instance.query.left ? triggerOptions.find((i) => i.value === instance.query.left) : null;
+ const unit = metric ? metric.unit : '';
+ const isThreshold = instance.detectionMethod === 'threshold';
- return (
-
+ }
+ />
- }
- />
-
-
-
- {!isThreshold && (
-
-
-
-
-
-
-
-
-
-
-
-
- {instance.exists() && (
-
- )}
-
-
-
- )
-}
-
-export default connect(state => ({
- instance: state.getIn(['alerts', 'instance']),
- triggerOptions: state.getIn(['alerts', 'triggerOptions']),
- loading: state.getIn(['alerts', 'saveRequest', 'loading']),
- deleting: state.getIn(['alerts', 'removeRequest', 'loading'])
-}), { fetchTriggerOptions })(AlertForm)
+export default connect(
+ (state) => ({
+ instance: state.getIn(['alerts', 'instance']),
+ triggerOptions: state.getIn(['alerts', 'triggerOptions']),
+ loading: state.getIn(['alerts', 'saveRequest', 'loading']),
+ deleting: state.getIn(['alerts', 'removeRequest', 'loading']),
+ }),
+ { fetchTriggerOptions }
+)(AlertForm);
diff --git a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx
index 8869f3a02..dc4c9db15 100644
--- a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx
+++ b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useState } from 'react';
import { SlideModal, IconButton } from 'UI';
import { init, edit, save, remove } from 'Duck/alerts';
import { fetchList as fetchWebhooks } from 'Duck/webhook';
@@ -9,93 +9,98 @@ import { EMAIL, SLACK, WEBHOOK } from 'App/constants/schedule';
import { confirm } from 'UI';
interface Props {
- showModal?: boolean;
- metricId?: number;
- onClose?: () => void;
- webhooks: any;
- fetchWebhooks: Function;
- save: Function;
- remove: Function;
- init: Function;
- edit: Function;
+ showModal?: boolean;
+ metricId?: number;
+ onClose?: () => void;
+ webhooks: any;
+ fetchWebhooks: Function;
+ save: Function;
+ remove: Function;
+ init: Function;
+ edit: Function;
}
function AlertFormModal(props: Props) {
- const { metricId = null, showModal = false, webhooks } = props;
- const [showForm, setShowForm] = useState(false);
+ const { metricId = null, showModal = false, webhooks } = props;
+ const [showForm, setShowForm] = useState(false);
- useEffect(() => {
- props.fetchWebhooks();
- }, [])
+ useEffect(() => {
+ props.fetchWebhooks();
+ }, []);
- const slackChannels = webhooks.filter(hook => hook.type === SLACK).map(({ webhookId, name }) => ({ value: webhookId, text: name })).toJS();
- const hooks = webhooks.filter(hook => hook.type === WEBHOOK).map(({ webhookId, name }) => ({ value: webhookId, text: name })).toJS();
+ const slackChannels = webhooks
+ .filter((hook) => hook.type === SLACK)
+ .map(({ webhookId, name }) => ({ value: webhookId, text: name }))
+ .toJS();
+ const hooks = webhooks
+ .filter((hook) => hook.type === WEBHOOK)
+ .map(({ webhookId, name }) => ({ value: webhookId, text: name }))
+ .toJS();
- const saveAlert = instance => {
- const wasUpdating = instance.exists();
- props.save(instance).then(() => {
- if (!wasUpdating) {
- toggleForm(null, false);
- }
- if (props.onClose) {
- props.onClose();
- }
- })
- }
+ const saveAlert = (instance) => {
+ const wasUpdating = instance.exists();
+ props.save(instance).then(() => {
+ if (!wasUpdating) {
+ toggleForm(null, false);
+ }
+ if (props.onClose) {
+ props.onClose();
+ }
+ });
+ };
- const onDelete = async (instance) => {
- if (await confirm({
- header: 'Confirm',
- confirmButton: 'Yes, delete',
- confirmation: `Are you sure you want to permanently delete this alert?`
- })) {
- props.remove(instance.alertId).then(() => {
- toggleForm(null, false);
- });
- }
- }
-
- const toggleForm = (instance, state) => {
- if (instance) {
- props.init(instance)
- }
- return setShowForm(state ? state : !showForm);
- }
-
- return (
-
- { 'Create Alert' }
- {/* toggleForm({}, true) }
- /> */}
-
+ const onDelete = async (instance) => {
+ if (
+ await confirm({
+ header: 'Confirm',
+ confirmButton: 'Yes, delete',
+ confirmation: `Are you sure you want to permanently delete this alert?`,
+ })
+ ) {
+ props.remove(instance.alertId).then(() => {
+ toggleForm(null, false);
+ });
}
- isDisplayed={ showModal }
- onClose={props.onClose}
- size="medium"
- content={ showModal &&
- {
+ if (instance) {
+ props.init(instance);
+ }
+ return setShowForm(state ? state : !showForm);
+ };
+
+ return (
+
+ {'Create Alert'}
+
+ }
+ isDisplayed={showModal}
onClose={props.onClose}
- onDelete={onDelete}
- style={{ width: '580px', height: '100vh - 200px' }}
- />
- }
- />
- );
+ size="medium"
+ content={
+ showModal && (
+
+ )
+ }
+ />
+ );
}
-export default connect(state => ({
- webhooks: state.getIn(['webhooks', 'list']),
- instance: state.getIn(['alerts', 'instance']),
-}), { init, edit, save, remove, fetchWebhooks, setShowAlerts })(AlertFormModal)
\ No newline at end of file
+export default connect(
+ (state) => ({
+ webhooks: state.getIn(['webhooks', 'list']),
+ instance: state.getIn(['alerts', 'instance']),
+ }),
+ { init, edit, save, remove, fetchWebhooks, setShowAlerts }
+)(AlertFormModal);
diff --git a/frontend/app/components/Alerts/Alerts.js b/frontend/app/components/Alerts/Alerts.js
index b24665a68..ed825abaf 100644
--- a/frontend/app/components/Alerts/Alerts.js
+++ b/frontend/app/components/Alerts/Alerts.js
@@ -10,95 +10,100 @@ import { setShowAlerts } from 'Duck/dashboard';
import { EMAIL, SLACK, WEBHOOK } from 'App/constants/schedule';
import { confirm } from 'UI';
-const Alerts = props => {
- const { webhooks, setShowAlerts } = props;
- const [showForm, setShowForm] = useState(false);
+const Alerts = (props) => {
+ const { webhooks, setShowAlerts } = props;
+ const [showForm, setShowForm] = useState(false);
- useEffect(() => {
- props.fetchWebhooks();
- }, [])
+ useEffect(() => {
+ props.fetchWebhooks();
+ }, []);
- const slackChannels = webhooks.filter(hook => hook.type === SLACK).map(({ webhookId, name }) => ({ value: webhookId, label: name })).toJS();
- const hooks = webhooks.filter(hook => hook.type === WEBHOOK).map(({ webhookId, name }) => ({ value: webhookId, label: name })).toJS();
+ const slackChannels = webhooks
+ .filter((hook) => hook.type === SLACK)
+ .map(({ webhookId, name }) => ({ value: webhookId, label: name }))
+ .toJS();
+ const hooks = webhooks
+ .filter((hook) => hook.type === WEBHOOK)
+ .map(({ webhookId, name }) => ({ value: webhookId, label: name }))
+ .toJS();
- const saveAlert = instance => {
- const wasUpdating = instance.exists();
- props.save(instance).then(() => {
- if (!wasUpdating) {
- toast.success('New alert saved')
- toggleForm(null, false);
- } else {
- toast.success('Alert updated')
- }
- })
- }
+ const saveAlert = (instance) => {
+ const wasUpdating = instance.exists();
+ props.save(instance).then(() => {
+ if (!wasUpdating) {
+ toast.success('New alert saved');
+ toggleForm(null, false);
+ } else {
+ toast.success('Alert updated');
+ }
+ });
+ };
- const onDelete = async (instance) => {
- if (await confirm({
- header: 'Confirm',
- confirmButton: 'Yes, delete',
- confirmation: `Are you sure you want to permanently delete this alert?`
- })) {
- props.remove(instance.alertId).then(() => {
- toggleForm(null, false);
- });
- }
- }
+ const onDelete = async (instance) => {
+ if (
+ await confirm({
+ header: 'Confirm',
+ confirmButton: 'Yes, delete',
+ confirmation: `Are you sure you want to permanently delete this alert?`,
+ })
+ ) {
+ props.remove(instance.alertId).then(() => {
+ toggleForm(null, false);
+ });
+ }
+ };
- const toggleForm = (instance, state) => {
- if (instance) {
- props.init(instance)
- }
- return setShowForm(state ? state : !showForm);
- }
+ const toggleForm = (instance, state) => {
+ if (instance) {
+ props.init(instance);
+ }
+ return setShowForm(state ? state : !showForm);
+ };
- return (
-
-
- { 'Alerts' }
- toggleForm({}, true) }
+ return (
+
+
+ {'Alerts'}
+ toggleForm({}, true)} />
+
+ }
+ isDisplayed={true}
+ onClose={() => {
+ toggleForm({}, false);
+ setShowAlerts(false);
+ }}
+ size="small"
+ content={
+ {
+ toggleForm(alert, true);
+ }}
+ onClickCreate={() => toggleForm({}, true)}
+ />
+ }
+ detailContent={
+ showForm && (
+ toggleForm({}, false)}
+ onDelete={onDelete}
+ />
+ )
+ }
/>
-
- }
- isDisplayed={ true }
- onClose={ () => {
- toggleForm({}, false);
- setShowAlerts(false);
- } }
- size="small"
- content={
- {
- toggleForm(alert, true)
- }}
- />
- }
- detailContent={
- showForm && (
- toggleForm({}, false) }
- onDelete={onDelete}
- />
- )
- }
- />
-
- )
-}
+
+ );
+};
-export default connect(state => ({
- webhooks: state.getIn(['webhooks', 'list']),
- instance: state.getIn(['alerts', 'instance']),
-}), { init, edit, save, remove, fetchWebhooks, setShowAlerts })(Alerts)
+export default connect(
+ (state) => ({
+ webhooks: state.getIn(['webhooks', 'list']),
+ instance: state.getIn(['alerts', 'instance']),
+ }),
+ { init, edit, save, remove, fetchWebhooks, setShowAlerts }
+)(Alerts);
diff --git a/frontend/app/components/Alerts/AlertsList.js b/frontend/app/components/Alerts/AlertsList.js
index 21ea6448d..5a874e0fa 100644
--- a/frontend/app/components/Alerts/AlertsList.js
+++ b/frontend/app/components/Alerts/AlertsList.js
@@ -1,55 +1,58 @@
-import React, { useEffect, useState } from 'react'
-import { Loader, NoContent, Input } from 'UI';
-import AlertItem from './AlertItem'
+import React, { useEffect, useState } from 'react';
+import { Loader, NoContent, Input, Button } from 'UI';
+import AlertItem from './AlertItem';
import { fetchList, init } from 'Duck/alerts';
import { connect } from 'react-redux';
import { getRE } from 'App/utils';
-const AlertsList = props => {
- const { loading, list, instance, onEdit } = props;
- const [query, setQuery] = useState('')
-
- useEffect(() => {
- props.fetchList()
- }, [])
+const AlertsList = (props) => {
+ const { loading, list, instance, onEdit } = props;
+ const [query, setQuery] = useState('');
- const filterRE = getRE(query, 'i');
- const _filteredList = list.filter(({ name, query: { left } }) => filterRE.test(name) || filterRE.test(left));
+ useEffect(() => {
+ props.fetchList();
+ }, []);
- return (
-
-
- setQuery(value)}
- />
-
-
-
-
- {_filteredList.map(a => (
-
-
onEdit(a.toData())}
- />
-
- ))}
-
-
-
-
- )
-}
+ const filterRE = getRE(query, 'i');
+ const _filteredList = list.filter(({ name, query: { left } }) => filterRE.test(name) || filterRE.test(left));
-export default connect(state => ({
- list: state.getIn(['alerts', 'list']).sort((a, b ) => b.createdAt - a.createdAt),
- instance: state.getIn(['alerts', 'instance']),
- loading: state.getIn(['alerts', 'loading'])
-}), { fetchList, init })(AlertsList)
+ return (
+
+
+ setQuery(value)} />
+
+
+
+ Alerts helps your team stay up to date with the activity on your app.
+
+
+ }
+ size="small"
+ show={list.size === 0}
+ >
+
+ {_filteredList.map((a) => (
+
+
onEdit(a.toData())} />
+
+ ))}
+
+
+
+
+ );
+};
+
+export default connect(
+ (state) => ({
+ list: state.getIn(['alerts', 'list']).sort((a, b) => b.createdAt - a.createdAt),
+ instance: state.getIn(['alerts', 'instance']),
+ loading: state.getIn(['alerts', 'loading']),
+ }),
+ { fetchList, init }
+)(AlertsList);
diff --git a/frontend/app/components/ui/NoContent/noContent.module.css b/frontend/app/components/ui/NoContent/noContent.module.css
index 9b525dc26..dd78c8bbc 100644
--- a/frontend/app/components/ui/NoContent/noContent.module.css
+++ b/frontend/app/components/ui/NoContent/noContent.module.css
@@ -12,7 +12,7 @@
transition: all 0.2s;
padding: 40px;
- &.small {
+ /* &.small {
& .title {
font-size: 20px !important;
}
@@ -20,7 +20,7 @@
& .subtext {
font-size: 16px;
}
- }
+ } */
}
.title {
diff --git a/frontend/app/types/alert.js b/frontend/app/types/alert.js
index c16f6a87e..244047a45 100644
--- a/frontend/app/types/alert.js
+++ b/frontend/app/types/alert.js
@@ -12,7 +12,7 @@ conditions.forEach(c => { conditionsMap[c.value] = c });
export default Record({
alertId: '',
projectId: undefined,
- name: 'New Alert',
+ name: 'Untitled Alert',
description: '',
active: true,
currentPeriod: 15,