From ef090aa696020684e0b257acbe195a76a9c5586c Mon Sep 17 00:00:00 2001 From: sylenien Date: Mon, 9 Jan 2023 14:52:45 +0100 Subject: [PATCH] fix(ui): remove old alerts --- frontend/app/components/Alerts/AlertForm.js | 26 ++-- .../Alerts/AlertFormModal/AlertFormModal.tsx | 39 ++++-- frontend/app/components/Alerts/AlertItem.js | 57 -------- .../app/components/Alerts/AlertTypeLabel.js | 13 -- frontend/app/components/Alerts/Alerts.js | 109 --------------- frontend/app/components/Alerts/AlertsList.js | 58 -------- .../Alerts/Notifications/ListItem/ListItem.js | 33 ----- .../Alerts/Notifications/ListItem/index.js | 1 - .../ListItem/listItem.module.css | 7 - .../components/Alerts/alertItem.module.css | 9 -- .../Alerts/alertTypeLabel.module.css | 11 -- .../app/components/Alerts/alerts.stories.js | 130 ------------------ frontend/app/components/Alerts/index.js | 1 - .../components/Alerts/AlertListItem.tsx | 2 +- .../DashboardView/DashboardView.tsx | 2 +- .../FunnelIssueDetails/FunnelIssueDetails.tsx | 2 +- .../Funnels/FunnelIssues/FunnelIssues.tsx | 2 +- .../WidgetSessions/WidgetSessions.tsx | 3 +- .../components/WidgetWrapper/AlertButton.tsx | 15 +- .../components/WidgetWrapper/WidgetIcon.tsx | 5 +- frontend/app/components/Header/Header.js | 4 - frontend/app/duck/alerts.js | 63 --------- frontend/app/duck/index.ts | 2 - frontend/app/mstore/alertsStore.ts | 8 +- frontend/app/mstore/dashboardStore.ts | 4 + frontend/app/types/alert.ts | 5 +- 26 files changed, 68 insertions(+), 543 deletions(-) delete mode 100644 frontend/app/components/Alerts/AlertItem.js delete mode 100644 frontend/app/components/Alerts/AlertTypeLabel.js delete mode 100644 frontend/app/components/Alerts/Alerts.js delete mode 100644 frontend/app/components/Alerts/AlertsList.js delete mode 100644 frontend/app/components/Alerts/Notifications/ListItem/ListItem.js delete mode 100644 frontend/app/components/Alerts/Notifications/ListItem/index.js delete mode 100644 frontend/app/components/Alerts/Notifications/ListItem/listItem.module.css delete mode 100644 frontend/app/components/Alerts/alertItem.module.css delete mode 100644 frontend/app/components/Alerts/alertTypeLabel.module.css delete mode 100644 frontend/app/components/Alerts/alerts.stories.js delete mode 100644 frontend/app/components/Alerts/index.js delete mode 100644 frontend/app/duck/alerts.js diff --git a/frontend/app/components/Alerts/AlertForm.js b/frontend/app/components/Alerts/AlertForm.js index 18ae1ac01..fcec66918 100644 --- a/frontend/app/components/Alerts/AlertForm.js +++ b/frontend/app/components/Alerts/AlertForm.js @@ -43,7 +43,7 @@ const Section = ({ index, title, description, content }) => ( ); -const AlertForm = (props) => { +function AlertForm(props) { const { slackChannels, msTeamsChannels, @@ -53,28 +53,28 @@ const AlertForm = (props) => { } = props; const { alertsStore } = useStore() const { - instance, triggerOptions, loading, } = alertsStore + const instance = alertsStore.instance const deleting = loading - 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 write = ({ target: { value, name } }) => alertsStore.edit({ [name]: value }); + const writeOption = (e, { name, value }) => alertsStore.edit({ [name]: value.value }); + const onChangeCheck = ({ target: { checked, name } }) => alertsStore.edit({ [name]: checked }); useEffect(() => { - alertsStore.fetchTriggerOptions(); + void alertsStore.fetchTriggerOptions(); }, []); const writeQueryOption = (e, { name, value }) => { const { query } = instance; - props.edit({ query: { ...query, [name]: value } }); + alertsStore.edit({ query: { ...query, [name]: value } }); }; const writeQuery = ({ target: { value, name } }) => { const { query } = instance; - props.edit({ query: { ...query, [name]: value } }); + alertsStore.edit({ query: { ...query, [name]: value } }); }; const metric = @@ -112,7 +112,7 @@ const AlertForm = (props) => { primary name="detectionMethod" className="my-3" - onSelect={(e, { name, value }) => props.edit({ [name]: value })} + onSelect={(e, { name, value }) => alertsStore.edit({ [name]: value })} value={{ value: instance.detectionMethod }} list={[ { name: 'Threshold', value: 'threshold' }, @@ -294,7 +294,7 @@ const AlertForm = (props) => { selected={instance.slackInput} options={slackChannels} placeholder="Select Channel" - onChange={(selected) => props.edit({ slackInput: selected })} + onChange={(selected) => alertsStore.edit({ slackInput: selected })} /> @@ -308,7 +308,7 @@ const AlertForm = (props) => { selected={instance.msteamsInput} options={msTeamsChannels} placeholder="Select Channel" - onChange={(selected) => props.edit({ msteamsInput: selected })} + onChange={(selected) => alertsStore.edit({ msteamsInput: selected })} /> @@ -323,7 +323,7 @@ const AlertForm = (props) => { validate={validateEmail} selected={instance.emailInput} placeholder="Type and press Enter key" - onChange={(selected) => props.edit({ emailInput: selected })} + onChange={(selected) => alertsStore.edit({ emailInput: selected })} /> @@ -337,7 +337,7 @@ const AlertForm = (props) => { selected={instance.webhookInput} options={webhooks} placeholder="Select Webhook" - onChange={(selected) => props.edit({ webhookInput: selected })} + onChange={(selected) => alertsStore.edit({ webhookInput: selected })} /> )} diff --git a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx index f03c479be..48a46a3a0 100644 --- a/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx +++ b/frontend/app/components/Alerts/AlertFormModal/AlertFormModal.tsx @@ -5,10 +5,15 @@ import { observer } from 'mobx-react-lite' import { fetchList as fetchWebhooks } from 'Duck/webhook'; import AlertForm from '../AlertForm'; import { connect } from 'react-redux'; -import { setShowAlerts } from 'Duck/dashboard'; -import { SLACK, WEBHOOK } from 'App/constants/schedule'; +import { SLACK, TEAMS, WEBHOOK } from 'App/constants/schedule'; import { confirm } from 'UI'; +interface Select { + label: string; + value: string | number +} + + interface Props { showModal?: boolean; metricId?: number; @@ -25,14 +30,23 @@ function AlertFormModal(props: Props) { 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: Select[] = [] + const hooks: Select[] = [] + const msTeamsChannels: Select[] = [] + + webhooks.forEach((hook) => { + const option = { value: hook.webhookId, label: hook.name } + if (hook.type === SLACK) { + slackChannels.push(option) + } + if (hook.type === WEBHOOK) { + hooks.push(option) + } + if (hook.type === TEAMS) { + msTeamsChannels.push(option) + } + }) const saveAlert = (instance) => { const wasUpdating = instance.exists(); @@ -71,7 +85,7 @@ function AlertFormModal(props: Props) { - {'Create Alert'} + {'Create Alert'} } isDisplayed={showModal} @@ -83,6 +97,7 @@ function AlertFormModal(props: Props) { metricId={metricId} edit={alertsStore.edit} slackChannels={slackChannels} + msTeamsChannels={msTeamsChannels} webhooks={hooks} onSubmit={saveAlert} onClose={props.onClose} @@ -99,5 +114,5 @@ export default connect( (state) => ({ webhooks: state.getIn(['webhooks', 'list']), }), - { fetchWebhooks, setShowAlerts } + { fetchWebhooks } )(observer(AlertFormModal)); diff --git a/frontend/app/components/Alerts/AlertItem.js b/frontend/app/components/Alerts/AlertItem.js deleted file mode 100644 index 76431bf77..000000000 --- a/frontend/app/components/Alerts/AlertItem.js +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react' -import cn from 'classnames'; -import stl from './alertItem.module.css'; -import AlertTypeLabel from './AlertTypeLabel'; - -const AlertItem = props => { - const { alert, onEdit, active } = props; - - const getThreshold = threshold => { - if (threshold === 15) return '15 Minutes'; - if (threshold === 30) return '30 Minutes'; - if (threshold === 60) return '1 Hour'; - if (threshold === 120) return '2 Hours'; - if (threshold === 240) return '4 Hours'; - if (threshold === 1440) return '1 Day'; - } - - const getNotifyChannel = alert => { - let str = ''; - if (alert.msteams) - str = 'MS Teams' - if (alert.slack) - str = 'Slack'; - if (alert.email) - str += (str === '' ? '' : ' and ')+ 'Email'; - if (alert.webhool) - str += (str === '' ? '' : ' and ')+ 'Webhook'; - if (str === '') - return 'OpenReplay'; - - return str; - } - - const isThreshold = alert.detectionMethod === 'threshold'; - - return ( -
- -
{alert.name}
-
- {alert.detectionMethod === 'threshold' && ( -
When {alert.metric.text} is {alert.condition.text} {alert.query.right} {alert.metric.unit} over the past {getThreshold(alert.currentPeriod)}, notify me on {getNotifyChannel(alert)}.
- )} - - {alert.detectionMethod === 'change' && ( -
When the {alert.options.change} of {alert.metric.text} is {alert.condition.text} {alert.query.right} {alert.metric.unit} over the past {getThreshold(alert.currentPeriod)} compared to the previous {getThreshold(alert.previousPeriod)}, notify me on {getNotifyChannel(alert)}.
- )} -
-
- ) -} - -export default AlertItem diff --git a/frontend/app/components/Alerts/AlertTypeLabel.js b/frontend/app/components/Alerts/AlertTypeLabel.js deleted file mode 100644 index f867dfdc4..000000000 --- a/frontend/app/components/Alerts/AlertTypeLabel.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' -import cn from 'classnames' -import stl from './alertTypeLabel.module.css' - -function AlertTypeLabel({ filterKey, type = '' }) { - return ( -
- { type } -
- ) -} - -export default AlertTypeLabel diff --git a/frontend/app/components/Alerts/Alerts.js b/frontend/app/components/Alerts/Alerts.js deleted file mode 100644 index ed825abaf..000000000 --- a/frontend/app/components/Alerts/Alerts.js +++ /dev/null @@ -1,109 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { toast } from 'react-toastify'; -import AlertsList from './AlertsList'; -import { SlideModal, IconButton } from 'UI'; -import { init, edit, save, remove } from 'Duck/alerts'; -import { fetchList as fetchWebhooks } from 'Duck/webhook'; -import AlertForm from './AlertForm'; -import { connect } from 'react-redux'; -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); - - 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 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 toggleForm = (instance, state) => { - if (instance) { - props.init(instance); - } - return setShowForm(state ? state : !showForm); - }; - - 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} - /> - ) - } - /> - - ); -}; - -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 deleted file mode 100644 index a64094a0d..000000000 --- a/frontend/app/components/Alerts/AlertsList.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Loader, NoContent, Input, Button } from 'UI'; -import AlertItem from './AlertItem'; -import { fetchList } 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 filterRE = getRE(query, 'i'); - const _filteredList = list.filter(({ name, query: { left } }) => filterRE.test(name) || filterRE.test(left)); - - 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 } -)(AlertsList); diff --git a/frontend/app/components/Alerts/Notifications/ListItem/ListItem.js b/frontend/app/components/Alerts/Notifications/ListItem/ListItem.js deleted file mode 100644 index 994ffcfb4..000000000 --- a/frontend/app/components/Alerts/Notifications/ListItem/ListItem.js +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import { Button } from 'UI'; -import stl from './listItem.module.css'; -import cn from 'classnames'; -import AlertTypeLabel from '../../AlertTypeLabel'; - -const ListItem = ({ alert, onClear, loading, onNavigate }) => { - return ( -
-
-
{alert.createdAt && alert.createdAt.toFormat('LLL dd, yyyy, hh:mm a')}
-
- -
-
- - -
-

- {alert.title} -

-
{alert.description}
-
-
- ) -} - -export default ListItem diff --git a/frontend/app/components/Alerts/Notifications/ListItem/index.js b/frontend/app/components/Alerts/Notifications/ListItem/index.js deleted file mode 100644 index 741aed270..000000000 --- a/frontend/app/components/Alerts/Notifications/ListItem/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ListItem'; diff --git a/frontend/app/components/Alerts/Notifications/ListItem/listItem.module.css b/frontend/app/components/Alerts/Notifications/ListItem/listItem.module.css deleted file mode 100644 index 8472a777c..000000000 --- a/frontend/app/components/Alerts/Notifications/ListItem/listItem.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.wrapper { - padding: 15px; -} - -.viewed { - background-color: $gray-lightest; -} \ No newline at end of file diff --git a/frontend/app/components/Alerts/alertItem.module.css b/frontend/app/components/Alerts/alertItem.module.css deleted file mode 100644 index fe26fe57e..000000000 --- a/frontend/app/components/Alerts/alertItem.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.wrapper { - &:hover { - background-color: $active-blue; - } - - &.active { - background-color: $active-blue; - } -} diff --git a/frontend/app/components/Alerts/alertTypeLabel.module.css b/frontend/app/components/Alerts/alertTypeLabel.module.css deleted file mode 100644 index 62ed31460..000000000 --- a/frontend/app/components/Alerts/alertTypeLabel.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.wrapper { - background-color: white; - color: $gray-dark; - border: solid thin $gray-light; -} - -.alert { - background: #C3E9EA; - color: #32888C; - border: none; -} diff --git a/frontend/app/components/Alerts/alerts.stories.js b/frontend/app/components/Alerts/alerts.stories.js deleted file mode 100644 index 781a7e734..000000000 --- a/frontend/app/components/Alerts/alerts.stories.js +++ /dev/null @@ -1,130 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import { List } from 'immutable'; -import Alert from 'Types/alert'; -import Notification from 'Types/notification'; -import Alerts from '.'; -import Notifications from './Notifications'; -import AlertsList from './AlertsList'; -import AlertForm from './AlertForm'; - -const list = [ - { - "alertId": 2, - "projectId": 1, - "name": "new alert", - "description": null, - "active": true, - "threshold": 240, - "detectionMethod": "threshold", - "query": { - "left": "avgPageLoad", - "right": 1.0, - "operator": ">=" - }, - "createdAt": 1591893324078, - "options": { - "message": [ - { - "type": "slack", - "value": "51" - }, - ], - "LastNotification": 1592929583000, - "renotifyInterval": 120 - } - }, - { - "alertId": 14, - "projectId": 1, - "name": "alert 19.06", - "description": null, - "active": true, - "threshold": 30, - "detectionMethod": "threshold", - "query": { - "left": "avgPageLoad", - "right": 3000.0, - "operator": ">=" - }, - "createdAt": 1592579750935, - "options": { - "message": [ - { - "type": "slack", - "value": "51" - } - ], - "renotifyInterval": 120 - } - }, - { - "alertId": 15, - "projectId": 1, - "name": "notify every 60min", - "description": null, - "active": true, - "threshold": 30, - "detectionMethod": "threshold", - "query": { - "left": "avgPageLoad", - "right": 1.0, - "operator": ">=" - }, - "createdAt": 1592848779604, - "options": { - "message": [ - { - "type": "slack", - "value": "51" - }, - ], - "LastNotification": 1599135058000, - "renotifyInterval": 60 - } - }, - { - "alertId": 21, - "projectId": 1, - "name": "always notify", - "description": null, - "active": true, - "threshold": 30, - "detectionMethod": "threshold", - "query": { - "left": "avgPageLoad", - "right": 1.0, - "operator": ">=" - }, - "createdAt": 1592849011350, - "options": { - "message": [ - { - "type": "slack", - "value": "51" - } - ], - "LastNotification": 1599135058000, - "renotifyInterval": 10 - } - } -] - -const notifications = List([ - { title: 'test', type: 'change', createdAt: 1591893324078, description: 'Lorem ipusm'}, - { title: 'test', type: 'threshold', createdAt: 1591893324078, description: 'Lorem ipusm'}, - { title: 'test', type: 'threshold', createdAt: 1591893324078, description: 'Lorem ipusm'}, - { title: 'test', type: 'threshold', createdAt: 1591893324078, description: 'Lorem ipusm'}, -]) -storiesOf('Alerts', module) - .add('Alerts', () => ( - - )) - .add('List', () => ( - - )) - .add('AlertForm', () => ( - - )) - .add('AlertNotifications', () => ( - - )) diff --git a/frontend/app/components/Alerts/index.js b/frontend/app/components/Alerts/index.js deleted file mode 100644 index 4f6a6f772..000000000 --- a/frontend/app/components/Alerts/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Alerts' \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/Alerts/AlertListItem.tsx b/frontend/app/components/Dashboard/components/Alerts/AlertListItem.tsx index 1022842c9..4a2a97283 100644 --- a/frontend/app/components/Dashboard/components/Alerts/AlertListItem.tsx +++ b/frontend/app/components/Dashboard/components/Alerts/AlertListItem.tsx @@ -131,7 +131,7 @@ function AlertListItem(props: Props) { {' is '} {alert.query.operator} - {numberWithCommas(alert.query.right)} {alert.metric.unit} + {numberWithCommas(alert.query.right)} {alert.metric?.unit} {' over the past '} {getThreshold( diff --git a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx index facb9fcfa..0cde69517 100644 --- a/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx +++ b/frontend/app/components/Dashboard/components/DashboardView/DashboardView.tsx @@ -87,7 +87,7 @@ function DashboardView(props: Props) { /> dashboardStore.updateKey('showAlertModal', false)} + onClose={() => dashboardStore.toggleAlertModal(false)} /> diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.tsx index 1ae1fe528..25ef7a0a0 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssueDetails/FunnelIssueDetails.tsx @@ -19,7 +19,7 @@ function FunnelIssueDetails(props: Props) { useEffect(() => { setLoading(true); - const _filters = { ...filter, series: widget.data.stages ? widget.toJsonDrilldown().map((item: any) => { + const _filters = { ...filter, series: widget.data.stages ? widget.series.map((item: any) => { return { ...item, filter: { diff --git a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx index 826e9a133..5e3564911 100644 --- a/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx +++ b/frontend/app/components/Dashboard/components/Funnels/FunnelIssues/FunnelIssues.tsx @@ -49,7 +49,7 @@ function FunnelIssues() { const depsString = JSON.stringify(widget.series); useEffect(() => { - debounceRequest({ ...filter, series: widget.toJsonDrilldown(), page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); + debounceRequest({ ...filter, series: widget.series, page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize }); }, [stages.length, drillDownPeriod, filter.filters, depsString, metricStore.sessionsPage]); return useObserver(() => ( diff --git a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx index ebb07b49c..ada2dd03b 100644 --- a/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetSessions/WidgetSessions.tsx @@ -81,9 +81,10 @@ function WidgetSessions(props: Props) { const customFilter = { ...filter, ...timeRange, filters: [ ...sessionStore.userFilter.filters, clickFilter]} debounceClickMapSearch(customFilter) } else { + console.log(widget) debounceRequest(widget.metricId, { ...filter, - series: widget.toJsonDrilldown(), + series: widget.series, page: metricStore.sessionsPage, limit: metricStore.sessionsPageSize, }); diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx index 78d858b3e..548bc9570 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/AlertButton.tsx @@ -1,7 +1,5 @@ import React from 'react'; -import { connect } from 'react-redux'; import WidgetIcon from './WidgetIcon'; -import { init as initAlert } from 'Duck/alerts'; import { useStore } from 'App/mstore'; interface Props { @@ -9,20 +7,21 @@ interface Props { initAlert: Function; } function AlertButton(props: Props) { - const { seriesId, initAlert } = props; - const { dashboardStore } = useStore(); + const { seriesId } = props; + const { dashboardStore, alertsStore } = useStore(); const onClick = () => { - initAlert({ query: { left: seriesId }}) - dashboardStore.updateKey('showAlertModal', true); + dashboardStore.toggleAlertModal(true); + alertsStore.init({ query: { left: seriesId }}) } return ( +
+
); } -export default connect(null, { initAlert })(AlertButton); \ No newline at end of file +export default AlertButton; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetIcon.tsx b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetIcon.tsx index bc804b2b8..b9714b33b 100644 --- a/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetIcon.tsx +++ b/frontend/app/components/Dashboard/components/WidgetWrapper/WidgetIcon.tsx @@ -3,15 +3,14 @@ import { Icon, Tooltip } from 'UI'; interface Props { className: string; - onClick: () => void; icon: string; tooltip: string; } function WidgetIcon(props: Props) { - const { className, onClick, icon, tooltip } = props; + const { className, icon, tooltip } = props; return ( -
+
{/* @ts-ignore */}
diff --git a/frontend/app/components/Header/Header.js b/frontend/app/components/Header/Header.js index b00ebb93b..7ef0028c9 100644 --- a/frontend/app/components/Header/Header.js +++ b/frontend/app/components/Header/Header.js @@ -12,7 +12,6 @@ import { init as initSite } from 'Duck/site'; import { getInitials } from 'App/utils'; import ErrorGenPanel from 'App/dev/components'; -import Alerts from '../Alerts/Alerts'; import { fetchListActive as fetchMetadata } from 'Duck/customField'; import { useStore } from 'App/mstore'; import { useObserver } from 'mobx-react-lite'; @@ -91,8 +90,6 @@ const Header = (props) => { {}
- - {showAlerts && } ); }; @@ -103,7 +100,6 @@ export default withRouter( account: state.getIn(['user', 'account']), siteId: state.getIn(['site', 'siteId']), sites: state.getIn(['site', 'list']), - showAlerts: state.getIn(['dashboard', 'showAlerts']), boardingCompletion: state.getIn(['dashboard', 'boardingCompletion']), }), { onLogoutClick: logout, initSite, fetchMetadata } diff --git a/frontend/app/duck/alerts.js b/frontend/app/duck/alerts.js deleted file mode 100644 index 31721ff45..000000000 --- a/frontend/app/duck/alerts.js +++ /dev/null @@ -1,63 +0,0 @@ -import Alert from 'Types/alert'; -import { Map } from 'immutable'; -import crudDuckGenerator from './tools/crudDuck'; -import { RequestTypes } from 'Duck/requestStateCreator'; -import { reduceDucks } from 'Duck/tools'; - -const name = 'alert' -const idKey = 'alertId'; -const crudDuck = crudDuckGenerator(name, (d) => new Alert(d), { idKey: idKey }); -export const { fetchList, init, edit, remove } = crudDuck.actions; -const FETCH_TRIGGER_OPTIONS = new RequestTypes(`${name}/FETCH_TRIGGER_OPTIONS`); -const CHANGE_SEARCH = `${name}/CHANGE_SEARCH` -console.log(fetchList(), init(), edit(), remove()) -const initialState = Map({ - definedPercent: 0, - triggerOptions: [], - alertsSearch: '', -}); - -const reducer = (state = initialState, action = {}) => { - switch (action.type) { - // case GENERATE_LINK.SUCCESS: - // return state.update( - // 'list', - // list => list - // .map(member => { - // if(member.id === action.id) { - // return Member({...member.toJS(), invitationLink: action.data.invitationLink }) - // } - // return member - // }) - // ); - case CHANGE_SEARCH: - return state.set('alertsSearch', action.search); - case FETCH_TRIGGER_OPTIONS.SUCCESS: - return state.set('triggerOptions', action.data.map(({ name, value }) => ({ label: name, value }))); - } - return state; -}; - -export function save(instance) { - return { - types: crudDuck.actionTypes.SAVE.toArray(), - call: client => client.post( instance[idKey] ? `/alerts/${ instance[idKey] }` : '/alerts', instance.toData()), - }; -} - -export function changeSearch(search) { - return { - type: CHANGE_SEARCH, - search, - }; -} - -export function fetchTriggerOptions() { - return { - types: FETCH_TRIGGER_OPTIONS.toArray(), - call: client => client.get('/alerts/triggers'), - }; -} - -// export default crudDuck.reducer; -export default reduceDucks(crudDuck, { initialState, reducer }).reducer; diff --git a/frontend/app/duck/index.ts b/frontend/app/duck/index.ts index 4e8e24d8f..5133d2a10 100644 --- a/frontend/app/duck/index.ts +++ b/frontend/app/duck/index.ts @@ -7,7 +7,6 @@ import assignments from './assignments'; import filters from './filters'; import funnelFilters from './funnelFilters'; import templates from './templates'; -import alerts from './alerts'; import dashboard from './dashboard'; import components from './components'; import sources from './sources'; @@ -32,7 +31,6 @@ const rootReducer = combineReducers({ funnelFilters, templates, - alerts, dashboard, components, members, diff --git a/frontend/app/mstore/alertsStore.ts b/frontend/app/mstore/alertsStore.ts index 744370671..da83610c6 100644 --- a/frontend/app/mstore/alertsStore.ts +++ b/frontend/app/mstore/alertsStore.ts @@ -6,7 +6,7 @@ export default class AlertsStore { alerts: Alert[] = []; triggerOptions: { label: string, value: string | number, unit?: string }[] = []; alertsSearch = ''; - // @ts-ignore + // @ts-ignore instance: Alert = new Alert({}, false); loading = false @@ -70,6 +70,8 @@ export default class AlertsStore { } edit = (diff: Partial) => { - Object.assign(this.instance, diff) + const key = Object.keys(diff)[0] + // @ts-ignore + this.instance[key] = diff[key] } -} \ No newline at end of file +} diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 897b90a03..141cc6761 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -405,6 +405,10 @@ export default class DashboardStore { }); } + toggleAlertModal(val: boolean) { + this.showAlertModal = val + } + fetchMetricChartData( metric: Widget, data: any, diff --git a/frontend/app/types/alert.ts b/frontend/app/types/alert.ts index ff127a240..052de7c1d 100644 --- a/frontend/app/types/alert.ts +++ b/frontend/app/types/alert.ts @@ -1,5 +1,6 @@ import { notEmptyString, validateNumber } from 'App/validate'; import { alertMetrics as metrics, alertConditions as conditions } from 'App/constants'; +import { makeAutoObservable } from 'mobx' const metricsMap = {} const conditionsMap = {} @@ -73,7 +74,7 @@ export default class Alert { detectionMethod: IAlert["detectionMethod"] detection_method: IAlert["detection_method"] change: IAlert["change"] - query:IAlert["query"] + query: IAlert["query"] options: IAlert["options"] createdAt?: IAlert["createdAt"] slack: IAlert["slack"] @@ -128,6 +129,8 @@ export default class Alert { hasNotification: !!slack || !!email || !!webhook, isExists, }) + + makeAutoObservable(this) } validate() {