diff --git a/http/swagger.yml b/http/swagger.yml index 258cd4aae8..322aa94cd2 100644 --- a/http/swagger.yml +++ b/http/swagger.yml @@ -8652,12 +8652,7 @@ components: description: The name of the organization that owns this Task. type: string status: - description: Starting state of the task. 'inactive' tasks are not run until they are updated to 'active' - default: active - type: string - enum: - - active - - inactive + $ref: "#/components/schemas/TaskStatusType" flux: description: The Flux script to run for this task. type: string @@ -8669,12 +8664,7 @@ components: type: object properties: status: - description: Starting state of the task. 'inactive' tasks are not run until they are updated to 'active' - default: active - type: string - enum: - - active - - inactive + $ref: "#/components/schemas/TaskStatusType" flux: description: The Flux script to run for this task. type: string diff --git a/ui/src/alerting/actions/checks.ts b/ui/src/alerting/actions/checks.ts index 408ed0be66..6b274aafba 100644 --- a/ui/src/alerting/actions/checks.ts +++ b/ui/src/alerting/actions/checks.ts @@ -20,6 +20,7 @@ export type Action = | ReturnType | ReturnType | ReturnType + | ReturnType export const setAllChecks = (status: RemoteDataState, checks?: Check[]) => ({ type: 'SET_ALL_CHECKS' as 'SET_ALL_CHECKS', @@ -36,11 +37,19 @@ export const removeCheck = (checkID: string) => ({ payload: {checkID}, }) -export const setCurrentCheck = (status: RemoteDataState, check?: Check) => ({ +export const setCurrentCheck = ( + status: RemoteDataState, + check?: Partial +) => ({ type: 'SET_CURRENT_CHECK' as 'SET_CURRENT_CHECK', payload: {status, check}, }) +export const updateCurrentCheck = (checkUpdate: Partial) => ({ + type: 'UPDATE_CURRENT_CHECK' as 'UPDATE_CURRENT_CHECK', + payload: {status, checkUpdate}, +}) + export const getChecks = () => async ( dispatch: Dispatch, getState: GetState diff --git a/ui/src/alerting/components/EditCheckEO.tsx b/ui/src/alerting/components/EditCheckEO.tsx new file mode 100644 index 0000000000..07c02bfac7 --- /dev/null +++ b/ui/src/alerting/components/EditCheckEO.tsx @@ -0,0 +1,110 @@ +// Libraries +import React, {FunctionComponent, useEffect} from 'react' +import {withRouter, WithRouterProps} from 'react-router' +import {connect} from 'react-redux' + +// Components +import {Overlay, SpinnerContainer, TechnoSpinner} from '@influxdata/clockface' +import VEOHeader from 'src/dashboards/components/VEOHeader' +import TimeMachine from 'src/timeMachine/components/TimeMachine' + +// Utils +import {createView} from 'src/shared/utils/view' + +// Actions +import { + updateCheck, + setCurrentCheck, + updateCurrentCheck, + getCurrentCheck, +} from 'src/alerting/actions/checks' +import {setActiveTimeMachine} from 'src/timeMachine/actions' + +// Types +import {Check, AppState, RemoteDataState, XYView, ViewType} from 'src/types' +import {TimeMachineEnum} from 'src/timeMachine/constants' + +interface DispatchProps { + updateCheck: typeof updateCheck + setCurrentCheck: typeof setCurrentCheck + updateCurrentCheck: typeof updateCurrentCheck + onSetActiveTimeMachine: typeof setActiveTimeMachine +} + +interface StateProps { + check: Partial + status: RemoteDataState +} + +type Props = WithRouterProps & DispatchProps & StateProps + +const EditCheckEditorOverlay: FunctionComponent = ({ + onSetActiveTimeMachine, + params, + check, + status, +}) => { + useEffect(() => { + getCurrentCheck(params.checkID) + onSetActiveTimeMachine(TimeMachineEnum.Alerting) + }, [params.checkID]) + + useEffect(() => { + // create view properties from check + const view = createView(ViewType.XY) + onSetActiveTimeMachine(TimeMachineEnum.Alerting, {view}) + }, [check.id]) + + const handleUpdateName = (name: string) => { + updateCurrentCheck({name}) + } + + const handleCancel = () => {} + + const handleSave = () => {} + // dont render time machine until active time machine is what we expect + + return ( + +
+ } + loading={status || RemoteDataState.Loading} + > + +
+ +
+
+
+
+ ) +} + +const mstp = (state: AppState): StateProps => { + const { + checks: { + current: {check, status}, + }, + } = state + + return {check, status} +} + +const mdtp: DispatchProps = { + updateCheck: updateCheck, + setCurrentCheck: setCurrentCheck, + updateCurrentCheck: updateCurrentCheck, + onSetActiveTimeMachine: setActiveTimeMachine, +} + +export default connect( + mstp, + mdtp +)(withRouter(EditCheckEditorOverlay)) diff --git a/ui/src/alerting/components/NewCheckEO.tsx b/ui/src/alerting/components/NewCheckEO.tsx new file mode 100644 index 0000000000..318e9863f3 --- /dev/null +++ b/ui/src/alerting/components/NewCheckEO.tsx @@ -0,0 +1,104 @@ +// Libraries +import React, {FunctionComponent, useEffect} from 'react' +import {connect} from 'react-redux' + +// Components +import {Overlay, SpinnerContainer, TechnoSpinner} from '@influxdata/clockface' +import VEOHeader from 'src/dashboards/components/VEOHeader' +import TimeMachine from 'src/timeMachine/components/TimeMachine' + +// Actions +import { + updateCheck, + setCurrentCheck, + updateCurrentCheck, +} from 'src/alerting/actions/checks' +import {setActiveTimeMachine} from 'src/timeMachine/actions' + +// Utils +import {createView} from 'src/shared/utils/view' + +// Types +import {Check, AppState, RemoteDataState, XYView, ViewType} from 'src/types' +import {DEFAULT_CHECK} from 'src/alerting/constants' +import {TimeMachineEnum} from 'src/timeMachine/constants' + +interface DispatchProps { + updateCheck: typeof updateCheck + setCurrentCheck: typeof setCurrentCheck + updateCurrentCheck: typeof updateCurrentCheck + onSetActiveTimeMachine: typeof setActiveTimeMachine +} + +interface StateProps { + check: Partial + status: RemoteDataState +} + +type Props = DispatchProps & StateProps + +const NewCheckOverlay: FunctionComponent = ({ + onSetActiveTimeMachine, + updateCurrentCheck, + setCurrentCheck, + status, + check, +}) => { + useEffect(() => { + setCurrentCheck(RemoteDataState.Done, DEFAULT_CHECK) + const view = createView(ViewType.XY) + onSetActiveTimeMachine(TimeMachineEnum.Alerting, {view}) + }, []) + + const handleUpdateName = (name: string) => { + updateCurrentCheck({name}) + } + + const handleCancel = () => {} + + const handleSave = () => {} + + return ( + +
+ } + loading={status || RemoteDataState.Loading} + > + +
+ +
+
+
+
+ ) +} + +const mstp = (state: AppState): StateProps => { + const { + checks: { + current: {check, status}, + }, + } = state + + return {check, status} +} + +const mdtp: DispatchProps = { + updateCheck: updateCheck, + setCurrentCheck: setCurrentCheck, + updateCurrentCheck: updateCurrentCheck, + onSetActiveTimeMachine: setActiveTimeMachine, +} + +export default connect( + mstp, + mdtp +)(NewCheckOverlay) diff --git a/ui/src/alerting/constants/index.ts b/ui/src/alerting/constants/index.ts index 7934b6e948..bee425a41a 100644 --- a/ui/src/alerting/constants/index.ts +++ b/ui/src/alerting/constants/index.ts @@ -9,11 +9,19 @@ import { NotificationRuleType, CheckStatusLevel, ThresholdType, + ThresholdCheck, } from 'src/types' export const DEFAULT_CHECK_NAME = 'Name this check' export const DEFAULT_NOTIFICATION_RULE_NAME = 'Name this notification rule' +export const DEFAULT_CHECK: Partial = { + name: DEFAULT_CHECK_NAME, + type: CheckType.Threshold, + status: CheckBase.StatusEnum.Active, + thresholds: [], +} + export const query: DashboardQuery = { text: 'this is query', editMode: QueryEditMode.Advanced, diff --git a/ui/src/alerting/reducers/checks.ts b/ui/src/alerting/reducers/checks.ts index 6ca5ab4a6e..44347cec80 100644 --- a/ui/src/alerting/reducers/checks.ts +++ b/ui/src/alerting/reducers/checks.ts @@ -8,7 +8,7 @@ import {Action} from 'src/alerting/actions/checks' export interface ChecksState { status: RemoteDataState list: Check[] - current: {status: RemoteDataState; check: Check} + current: {status: RemoteDataState; check: Partial} } export const defaultChecksState: ChecksState = { @@ -52,6 +52,13 @@ export default ( if (action.payload.check) { draftState.current.check = action.payload.check } + return + case 'UPDATE_CURRENT_CHECK': + draftState.current.check = { + ...draftState.current.check, + ...action.payload.checkUpdate, + } as Check + return } }) diff --git a/ui/src/dashboards/actions/index.ts b/ui/src/dashboards/actions/index.ts index 88d82fb7be..765f9ac876 100644 --- a/ui/src/dashboards/actions/index.ts +++ b/ui/src/dashboards/actions/index.ts @@ -336,13 +336,13 @@ export const deleteDashboardAsync = (dashboard: Dashboard) => async ( } export const refreshDashboardVariableValues = ( - dashboard: Dashboard, + dashboardID: string, nextViews: View[] ) => (dispatch, getState: GetState) => { const variables = extractVariablesList(getState()) const variablesInUse = filterUnusedVars(variables, nextViews) - return dispatch(refreshVariableValues(dashboard.id, variablesInUse)) + return dispatch(refreshVariableValues(dashboardID, variablesInUse)) } export const getDashboardAsync = (dashboardID: string) => async ( @@ -363,7 +363,7 @@ export const getDashboardAsync = (dashboardID: string) => async ( dispatch(setViews(RemoteDataState.Done, views)) // Ensure the values for the variables in use on the dashboard are populated - await dispatch(refreshDashboardVariableValues(dashboard, views)) + await dispatch(refreshDashboardVariableValues(dashboard.id, views)) // Now that all the necessary state has been loaded, set the dashboard dispatch(setDashboard(dashboard)) @@ -390,18 +390,24 @@ export const updateDashboardAsync = (dashboard: Dashboard) => async ( } export const createCellWithView = ( - dashboard: Dashboard, + dashboardID: string, view: NewView, clonedCell?: Cell ) => async (dispatch, getState: GetState): Promise => { try { + const state = getState() + let dashboard = state.dashboards.list.find(d => d.id === dashboardID) + if (!dashboard) { + dashboard = await getDashboardAJAX(dashboardID) + } + const cell: CreateCell = getNewDashboardCell(dashboard, clonedCell) // Create the cell - const createdCell = await addCellAJAX(dashboard.id, cell) + const createdCell = await addCellAJAX(dashboardID, cell) // Create the view and associate it with the cell - const newView = await updateViewAJAX(dashboard.id, createdCell.id, view) + const newView = await updateViewAJAX(dashboardID, createdCell.id, view) // Update the dashboard with the new cell let updatedDashboard: Dashboard = { @@ -412,9 +418,9 @@ export const createCellWithView = ( updatedDashboard = await updateDashboardAJAX(dashboard) // Refresh variables in use on dashboard - const views = [...getViewsForDashboard(getState(), dashboard.id), newView] + const views = [...getViewsForDashboard(state, dashboard.id), newView] - await dispatch(refreshDashboardVariableValues(dashboard, views)) + await dispatch(refreshDashboardVariableValues(dashboard.id, views)) dispatch(setView(createdCell.id, newView, RemoteDataState.Done)) dispatch(editDashboard(updatedDashboard)) @@ -423,20 +429,20 @@ export const createCellWithView = ( } } -export const updateView = (dashboard: Dashboard, view: View) => async ( +export const updateView = (dashboardID: string, view: View) => async ( dispatch, getState: GetState ) => { const cellID = view.cellID try { - const newView = await updateViewAJAX(dashboard.id, cellID, view) + const newView = await updateViewAJAX(dashboardID, cellID, view) - const views = getViewsForDashboard(getState(), dashboard.id) + const views = getViewsForDashboard(getState(), dashboardID) views.splice(views.findIndex(v => v.id === newView.id), 1, newView) - await dispatch(refreshDashboardVariableValues(dashboard, views)) + await dispatch(refreshDashboardVariableValues(dashboardID, views)) dispatch(setView(cellID, newView, RemoteDataState.Done)) } catch (e) { @@ -473,7 +479,7 @@ export const deleteCellAsync = (dashboard: Dashboard, cell: Cell) => async ( await Promise.all([ deleteCellAJAX(dashboard.id, cell), - dispatch(refreshDashboardVariableValues(dashboard, views)), + dispatch(refreshDashboardVariableValues(dashboard.id, views)), ]) dispatch(removeCell(dashboard, cell)) @@ -577,7 +583,7 @@ export const convertToTemplate = (dashboardID: string) => async ( } } -export const saveVEOView = (dashboard: Dashboard) => async ( +export const saveVEOView = (dashboardID: string) => async ( dispatch, getState: GetState ): Promise => { @@ -585,12 +591,13 @@ export const saveVEOView = (dashboard: Dashboard) => async ( try { if (view.id) { - await dispatch(updateView(dashboard, view)) + await dispatch(updateView(dashboardID, view)) } else { - await dispatch(createCellWithView(dashboard, view)) + await dispatch(createCellWithView(dashboardID, view)) } } catch (error) { console.error(error) dispatch(notify(copy.cellAddFailed())) + throw error } } diff --git a/ui/src/dashboards/actions/notes.ts b/ui/src/dashboards/actions/notes.ts index ff20f04dfc..beac56bd7d 100644 --- a/ui/src/dashboards/actions/notes.ts +++ b/ui/src/dashboards/actions/notes.ts @@ -76,7 +76,7 @@ export const createNoteCell = (dashboardID: string) => async ( view.properties.note = note - return dispatch(createCellWithView(dashboard, view)) + return dispatch(createCellWithView(dashboard.id, view)) } export interface ResetNoteStateAction { diff --git a/ui/src/dashboards/actions/views.ts b/ui/src/dashboards/actions/views.ts index 34ae8ed6ee..cee19f5733 100644 --- a/ui/src/dashboards/actions/views.ts +++ b/ui/src/dashboards/actions/views.ts @@ -5,9 +5,14 @@ import { } from 'src/dashboards/apis/' // Types -import {RemoteDataState} from 'src/types' +import {RemoteDataState, QueryView} from 'src/types' import {Dispatch} from 'redux' import {View} from 'src/types' +import {Action as TimeMachineAction} from 'src/timeMachine/actions' + +//Actions +import {setActiveTimeMachine} from 'src/timeMachine/actions' +import {TimeMachineEnum} from 'src/timeMachine/constants' export type Action = SetViewAction | SetViewsAction | ResetViewsAction @@ -83,3 +88,19 @@ export const updateView = (dashboardID: string, view: View) => async ( dispatch(setView(viewID, null, RemoteDataState.Error)) } } + +export const getViewForTimeMachine = ( + dashboardID: string, + cellID: string, + timeMachineID: TimeMachineEnum +) => async (dispatch: Dispatch): Promise => { + dispatch(setView(cellID, null, RemoteDataState.Loading)) + try { + const view = (await getViewAJAX(dashboardID, cellID)) as QueryView + + dispatch(setView(cellID, view, RemoteDataState.Done)) + dispatch(setActiveTimeMachine(timeMachineID, {view})) + } catch { + dispatch(setView(cellID, null, RemoteDataState.Error)) + } +} diff --git a/ui/src/dashboards/components/DashboardPage.tsx b/ui/src/dashboards/components/DashboardPage.tsx index 5b05f77c16..85d149d3ec 100644 --- a/ui/src/dashboards/components/DashboardPage.tsx +++ b/ui/src/dashboards/components/DashboardPage.tsx @@ -27,7 +27,6 @@ import { // Utils import {GlobalAutoRefresher} from 'src/utils/AutoRefresher' -import {createView} from 'src/shared/utils/view' import { extractRateLimitResourceName, extractRateLimitStatus, @@ -38,7 +37,6 @@ import { DASHBOARD_LAYOUT_ROW_HEIGHT, AUTOREFRESH_DEFAULT, } from 'src/shared/constants' -import {VEO_TIME_MACHINE_ID} from 'src/timeMachine/constants' import {DEFAULT_TIME_RANGE} from 'src/shared/constants/timeRanges' // Types @@ -51,9 +49,6 @@ import { AppState, AutoRefresh, AutoRefreshStatus, - XYView, - ViewType, - QueryView, } from 'src/types' import {RemoteDataState} from 'src/types' import {WithRouterProps} from 'react-router' @@ -299,7 +294,8 @@ class DashboardPage extends Component { } private handleAddCell = async (): Promise => { - this.showVEO() + const {router, location} = this.props + router.push(`${location.pathname}/cells/new`) } private showNoteOverlay = async (id?: string): Promise => { @@ -311,27 +307,15 @@ class DashboardPage extends Component { } private handleEditView = (cellID: string): void => { - this.showVEO(cellID) - } - - private showVEO = (id?: string): void => { - const {router, location, views, onSetActiveTimeMachine} = this.props - if (id) { - const view = _.get(views, `${id}.view`) as QueryView - onSetActiveTimeMachine(VEO_TIME_MACHINE_ID, {view}) - router.push(`${location.pathname}/cells/${id}/edit`) - } else { - const view = createView(ViewType.XY) - onSetActiveTimeMachine(VEO_TIME_MACHINE_ID, {view}) - router.push(`${location.pathname}/cells/new`) - } + const {router, location} = this.props + router.push(`${location.pathname}/cells/${cellID}/edit`) } private handleCloneCell = async (cell: Cell): Promise => { const {dashboard, onCreateCellWithView, views} = this.props const viewEntry = views[cell.id] if (viewEntry && viewEntry.view) { - await onCreateCellWithView(dashboard, viewEntry.view, cell) + await onCreateCellWithView(dashboard.id, viewEntry.view, cell) } } diff --git a/ui/src/dashboards/components/EditVEO.tsx b/ui/src/dashboards/components/EditVEO.tsx new file mode 100644 index 0000000000..10db61af75 --- /dev/null +++ b/ui/src/dashboards/components/EditVEO.tsx @@ -0,0 +1,139 @@ +// Libraries +import React, {FunctionComponent, useEffect} from 'react' +import {withRouter, WithRouterProps} from 'react-router' +import {connect} from 'react-redux' +import {get} from 'lodash' + +// Components +import {Overlay, SpinnerContainer, TechnoSpinner} from '@influxdata/clockface' +import TimeMachine from 'src/timeMachine/components/TimeMachine' +import VEOHeader from 'src/dashboards/components/VEOHeader' + +// Actions +import {setActiveTimeMachine} from 'src/timeMachine/actions' +import {setName} from 'src/timeMachine/actions' +import {saveVEOView} from 'src/dashboards/actions' +import {setView, getViewForTimeMachine} from 'src/dashboards/actions/views' + +// Utils +import {getActiveTimeMachine} from 'src/timeMachine/selectors' +import {TimeMachineEnum} from 'src/timeMachine/constants' + +// Types +import {AppState, RemoteDataState, View, QueryView} from 'src/types' +import {ViewsState} from 'src/dashboards/reducers/views' +import {executeQueries} from 'src/timeMachine/actions/queries' + +interface DispatchProps { + onSetActiveTimeMachine: typeof setActiveTimeMachine + onSetName: typeof setName + onSaveView: typeof saveVEOView + setView: typeof setView + executeQueries: typeof executeQueries + getViewForTimeMachine: typeof getViewForTimeMachine +} + +interface StateProps { + view: View + loadingState: RemoteDataState + views: ViewsState +} + +type Props = DispatchProps & StateProps & WithRouterProps + +const NewViewVEO: FunctionComponent = ({ + onSetActiveTimeMachine, + getViewForTimeMachine, + executeQueries, + loadingState, + onSaveView, + onSetName, + params, + router, + views, + view, +}) => { + useEffect(() => { + onSetActiveTimeMachine(TimeMachineEnum.VEO, {}) + + const viewInState = get(views, `${params.cellID}.view`, null) as QueryView + if (viewInState) { + onSetActiveTimeMachine(TimeMachineEnum.VEO, {view: viewInState}) + } else { + getViewForTimeMachine( + params.dashboardID, + params.cellID, + TimeMachineEnum.VEO + ) + } + }, [params.cellID]) + + useEffect(() => { + executeQueries() + }, [get(view, 'id', null)]) + + const handleClose = () => { + const {orgID, dashboardID} = params + router.push(`/orgs/${orgID}/dashboards/${dashboardID}`) + } + + const handleSave = () => { + try { + onSaveView(params.dashboardID) + handleClose() + } catch (e) {} + } + + return ( + +
+ } + loading={loadingState} + > + +
+ +
+
+
+
+ ) +} + +const mstp = (state: AppState, {params: {cellID}}): StateProps => { + const {activeTimeMachineID} = state.timeMachines + const {view} = getActiveTimeMachine(state) + + const viewMatchesRoute = get(view, 'id', null) === cellID + + let loadingState = RemoteDataState.Loading + + if (activeTimeMachineID === TimeMachineEnum.VEO && viewMatchesRoute) { + loadingState = RemoteDataState.Done + } + + const {views} = state + + return {view, loadingState, views} +} + +const mdtp: DispatchProps = { + onSetName: setName, + setView: setView, + onSaveView: saveVEOView, + onSetActiveTimeMachine: setActiveTimeMachine, + executeQueries: executeQueries, + getViewForTimeMachine: getViewForTimeMachine, +} + +export default connect( + mstp, + mdtp +)(withRouter(NewViewVEO)) diff --git a/ui/src/dashboards/components/NewVEO.tsx b/ui/src/dashboards/components/NewVEO.tsx new file mode 100644 index 0000000000..7fc18269c5 --- /dev/null +++ b/ui/src/dashboards/components/NewVEO.tsx @@ -0,0 +1,111 @@ +// Libraries +import React, {FunctionComponent, useEffect} from 'react' +import {withRouter, WithRouterProps} from 'react-router' +import {connect} from 'react-redux' +import {get} from 'lodash' + +// Components +import {Overlay, SpinnerContainer, TechnoSpinner} from '@influxdata/clockface' +import TimeMachine from 'src/timeMachine/components/TimeMachine' +import VEOHeader from 'src/dashboards/components/VEOHeader' + +// Actions +import {setActiveTimeMachine} from 'src/timeMachine/actions' +import {setName} from 'src/timeMachine/actions' +import {saveVEOView} from 'src/dashboards/actions' + +// Utils +import {getActiveTimeMachine} from 'src/timeMachine/selectors' +import {createView} from 'src/shared/utils/view' +import {TimeMachineEnum} from 'src/timeMachine/constants' + +// Types +import {AppState, ViewType, XYView, RemoteDataState, View} from 'src/types' + +interface DispatchProps { + onSetActiveTimeMachine: typeof setActiveTimeMachine + onSetName: typeof setName + onSaveView: typeof saveVEOView +} + +interface StateProps { + view: View + loadingState: RemoteDataState +} + +type Props = DispatchProps & StateProps & WithRouterProps + +const NewViewVEO: FunctionComponent = ({ + onSetActiveTimeMachine, + loadingState, + onSaveView, + onSetName, + params, + router, + view, +}) => { + useEffect(() => { + const view = createView(ViewType.XY) + onSetActiveTimeMachine(TimeMachineEnum.VEO, {view}) + }, []) + + const handleClose = () => { + const {orgID, dashboardID} = params + router.push(`/orgs/${orgID}/dashboards/${dashboardID}`) + } + + const handleSave = () => { + try { + onSaveView(params.dashboardID) + handleClose() + } catch (e) {} + } + + return ( + +
+ } + loading={loadingState} + > + +
+ +
+
+
+
+ ) +} + +const mstp = (state: AppState): StateProps => { + const {activeTimeMachineID} = state.timeMachines + const {view} = getActiveTimeMachine(state) + + const viewIsNew = !get(view, 'id', null) + + let loadingState = RemoteDataState.Loading + + if (activeTimeMachineID === TimeMachineEnum.VEO && viewIsNew) { + loadingState = RemoteDataState.Done + } + + return {view, loadingState} +} + +const mdtp: DispatchProps = { + onSetName: setName, + onSaveView: saveVEOView, + onSetActiveTimeMachine: setActiveTimeMachine, +} + +export default connect( + mstp, + mdtp +)(withRouter(NewViewVEO)) diff --git a/ui/src/dashboards/components/VEO.tsx b/ui/src/dashboards/components/VEO.tsx deleted file mode 100644 index d055f93cb9..0000000000 --- a/ui/src/dashboards/components/VEO.tsx +++ /dev/null @@ -1,103 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' -import {withRouter, WithRouterProps} from 'react-router' -import {connect} from 'react-redux' -import _ from 'lodash' - -// Components -import {SpinnerContainer, TechnoSpinner, Overlay} from '@influxdata/clockface' -import VEOContents from 'src/dashboards/components/VEOContents' - -// Utils -import {getView} from 'src/dashboards/selectors' -import {createView} from 'src/shared/utils/view' - -// Types -import {AppState, ViewType, QueryView, XYView, RemoteDataState} from 'src/types' -import {setActiveTimeMachine} from 'src/timeMachine/actions' - -interface OwnProps extends WithRouterProps { - params: { - dashboardID: string - cellID?: string - orgID: string - } -} - -interface StateProps { - viewsStatus: RemoteDataState - view: QueryView -} - -interface DispatchProps { - onSetActiveTimeMachine: typeof setActiveTimeMachine -} - -type Props = StateProps & DispatchProps & OwnProps - -class VEO extends PureComponent { - public render() { - const {params} = this.props - - return ( - -
- } - loading={this.loading} - > - - -
-
- ) - } - - private get loading(): RemoteDataState { - const {viewsStatus, view} = this.props - - if (viewsStatus === RemoteDataState.Done && view) { - return RemoteDataState.Done - } else if (viewsStatus === RemoteDataState.Done) { - return RemoteDataState.Error - } - - return viewsStatus - } - - private handleClose = () => { - const { - router, - params: {dashboardID, orgID}, - } = this.props - - router.push(`/orgs/${orgID}/dashboards/${dashboardID}`) - } -} - -const mstp = (state: AppState, {params}): StateProps => { - const {cellID} = params - const { - views: {status}, - } = state - - if (cellID) { - const view = getView(state, cellID) as QueryView - return {view, viewsStatus: status} - } - - const view = createView(ViewType.XY) - return {view, viewsStatus: status} -} - -const mdtp: DispatchProps = { - onSetActiveTimeMachine: setActiveTimeMachine, -} - -export default connect( - mstp, - mdtp -)(withRouter(VEO)) diff --git a/ui/src/dashboards/components/VEOContents.tsx b/ui/src/dashboards/components/VEOContents.tsx deleted file mode 100644 index d4df94a76c..0000000000 --- a/ui/src/dashboards/components/VEOContents.tsx +++ /dev/null @@ -1,92 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' -import {connect} from 'react-redux' -import _ from 'lodash' - -// Components -import VEOHeader from 'src/dashboards/components/VEOHeader' -import TimeMachine from 'src/timeMachine/components/TimeMachine' - -// Actions -import {setName} from 'src/timeMachine/actions' -import {saveVEOView} from 'src/dashboards/actions' -import {executeQueries} from 'src/timeMachine/actions/queries' - -// Utils -import {getActiveTimeMachine} from 'src/timeMachine/selectors' - -// Types -import {AppState} from 'src/types' -import {Dashboard} from 'src/types' - -interface StateProps { - name: string - dashboard: Dashboard -} - -interface DispatchProps { - onSetName: typeof setName - onSaveView: typeof saveVEOView - executeQueries: typeof executeQueries -} - -interface OwnProps { - dashboardID: string - onClose: () => void -} - -type Props = OwnProps & StateProps & DispatchProps - -class VEOContents extends PureComponent { - public componentDidMount() { - this.props.executeQueries() - } - - public render() { - const {name, onSetName} = this.props - - return ( - <> - -
- -
- - ) - } - - private handleSave = async (): Promise => { - const {dashboard, onSaveView, onClose} = this.props - - onSaveView(dashboard) - onClose() - } -} - -const mstp = (state: AppState, {dashboardID}): StateProps => { - const {dashboards} = state - const dashboard = dashboards.list.find(d => d.id === dashboardID) - - const { - view: {name}, - } = getActiveTimeMachine(state) - - return {name, dashboard} -} - -const mdtp: DispatchProps = { - onSetName: setName, - onSaveView: saveVEOView, - executeQueries, -} - -export default connect( - mstp, - mdtp -)(VEOContents) diff --git a/ui/src/dataExplorer/components/DataExplorer.tsx b/ui/src/dataExplorer/components/DataExplorer.tsx index e124d6f41a..ce6d458d1c 100644 --- a/ui/src/dataExplorer/components/DataExplorer.tsx +++ b/ui/src/dataExplorer/components/DataExplorer.tsx @@ -11,7 +11,7 @@ import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert' import {setActiveTimeMachine} from 'src/timeMachine/actions' // Utils -import {DE_TIME_MACHINE_ID} from 'src/timeMachine/constants' +import {TimeMachineEnum} from 'src/timeMachine/constants' import {HoverTimeProvider} from 'src/dashboards/utils/hoverTime' import {queryBuilderFetcher} from 'src/timeMachine/apis/QueryBuilderFetcher' import { @@ -37,7 +37,7 @@ class DataExplorer extends PureComponent { constructor(props: Props) { super(props) - props.onSetActiveTimeMachine(DE_TIME_MACHINE_ID) + props.onSetActiveTimeMachine(TimeMachineEnum.DE) queryBuilderFetcher.clearCache() } diff --git a/ui/src/dataExplorer/components/SaveAsCellForm.tsx b/ui/src/dataExplorer/components/SaveAsCellForm.tsx index de61ab2d3b..950befb842 100644 --- a/ui/src/dataExplorer/components/SaveAsCellForm.tsx +++ b/ui/src/dataExplorer/components/SaveAsCellForm.tsx @@ -170,7 +170,7 @@ class SaveAsCellForm extends PureComponent { } else { const selectedDashboard = dashboards.find(d => d.id === dashID) targetDashboardName = selectedDashboard.name - onCreateCellWithView(selectedDashboard, viewWithProps) + onCreateCellWithView(selectedDashboard.id, viewWithProps) } notify(cellAdded(cellName, targetDashboardName)) } catch { @@ -195,7 +195,7 @@ class SaveAsCellForm extends PureComponent { cells: [], } const dashboard = await createDashboard(newDashboard) - onCreateCellWithView(dashboard, view) + onCreateCellWithView(dashboard.id, view) } catch (error) { console.error(error) } diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 6ce53fe948..8c806dd349 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -39,7 +39,8 @@ import GetMe from 'src/shared/containers/GetMe' import Notifications from 'src/shared/containers/Notifications' import TaskExportOverlay from 'src/tasks/components/TaskExportOverlay' import TaskImportOverlay from 'src/tasks/components/TaskImportOverlay' -import VEO from 'src/dashboards/components/VEO' +import EditVEO from 'src/dashboards/components/EditVEO' +import NewVEO from 'src/dashboards/components/NewVEO' import NoteEditorOverlay from 'src/dashboards/components/NoteEditorOverlay' import OnboardingWizardPage from 'src/onboarding/containers/OnboardingWizardPage' import BucketsIndex from 'src/buckets/containers/BucketsIndex' @@ -78,6 +79,8 @@ import AlertingIndex from 'src/alerting/containers/AlertingIndex' import AlertHistoryIndex from 'src/alerting/containers/AlertHistoryIndex' import BucketsDeleteDataOverlay from 'src/shared/components/DeleteDataOverlay' import DEDeleteDataOverlay from 'src/dataExplorer/components/DeleteDataOverlay' +import NewCheckEO from 'src/alerting/components/NewCheckEO' +import EditCheckEO from 'src/alerting/components/EditCheckEO' import {FeatureFlag} from 'src/shared/utils/featureFlag' @@ -195,8 +198,8 @@ class Root extends PureComponent { component={DashboardPage} > - - + + @@ -313,7 +316,13 @@ class Root extends PureComponent { /> - + + + + } } export const setActiveTimeMachine = ( - activeTimeMachineID: string, + activeTimeMachineID: TimeMachineEnum, initialState: Partial = {} ): SetActiveTimeMachineAction => ({ type: 'SET_ACTIVE_TIME_MACHINE', diff --git a/ui/src/timeMachine/constants/index.ts b/ui/src/timeMachine/constants/index.ts index 5adb7a6177..a4946949c6 100644 --- a/ui/src/timeMachine/constants/index.ts +++ b/ui/src/timeMachine/constants/index.ts @@ -1,2 +1,5 @@ -export const DE_TIME_MACHINE_ID = 'de' -export const VEO_TIME_MACHINE_ID = 'veo' +export enum TimeMachineEnum { + DE = 'de', + VEO = 'veo', + Alerting = 'alerting', +} diff --git a/ui/src/timeMachine/reducers/index.test.ts b/ui/src/timeMachine/reducers/index.test.ts index c26ce7cc87..b0049e941b 100644 --- a/ui/src/timeMachine/reducers/index.test.ts +++ b/ui/src/timeMachine/reducers/index.test.ts @@ -26,10 +26,7 @@ import { import {createView} from 'src/shared/utils/view' // Constants -import { - DE_TIME_MACHINE_ID, - VEO_TIME_MACHINE_ID, -} from 'src/timeMachine/constants' +import {TimeMachineEnum} from 'src/timeMachine/constants' // Types import {TimeMachineTab} from 'src/types/timeMachine' @@ -43,10 +40,10 @@ import {selectAggregateWindow} from '../actions/queryBuilder' describe('timeMachinesReducer', () => { test('it directs actions to the currently active timeMachine', () => { const state = initialState() - const de = state.timeMachines[DE_TIME_MACHINE_ID] - const veo = state.timeMachines[VEO_TIME_MACHINE_ID] + const de = state.timeMachines[TimeMachineEnum.DE] + const veo = state.timeMachines[TimeMachineEnum.VEO] - expect(state.activeTimeMachineID).toEqual(DE_TIME_MACHINE_ID) + expect(state.activeTimeMachineID).toEqual(TimeMachineEnum.DE) expect(de.activeTab).toEqual(TimeMachineTab.Queries) expect(veo.activeTab).toEqual(TimeMachineTab.Queries) @@ -55,8 +52,8 @@ describe('timeMachinesReducer', () => { setActiveTab(TimeMachineTab.Visualization) ) - const nextDE = nextState.timeMachines[DE_TIME_MACHINE_ID] - const nextVEO = nextState.timeMachines[VEO_TIME_MACHINE_ID] + const nextDE = nextState.timeMachines[TimeMachineEnum.DE] + const nextVEO = nextState.timeMachines[TimeMachineEnum.VEO] expect(nextDE.activeTab).toEqual(TimeMachineTab.Visualization) expect(nextVEO.activeTab).toEqual(TimeMachineTab.Queries) @@ -65,7 +62,7 @@ describe('timeMachinesReducer', () => { test('it resets tab and draftScript state on a timeMachine when activated', () => { const state = initialState() - expect(state.activeTimeMachineID).toEqual(DE_TIME_MACHINE_ID) + expect(state.activeTimeMachineID).toEqual(TimeMachineEnum.DE) const activeTimeMachine = state.timeMachines[state.activeTimeMachineID] @@ -100,10 +97,10 @@ describe('timeMachinesReducer', () => { const nextState = timeMachinesReducer( state, - setActiveTimeMachine(VEO_TIME_MACHINE_ID, {view}) + setActiveTimeMachine(TimeMachineEnum.VEO, {view}) ) - expect(nextState.activeTimeMachineID).toEqual(VEO_TIME_MACHINE_ID) + expect(nextState.activeTimeMachineID).toEqual(TimeMachineEnum.VEO) const nextTimeMachine = nextState.timeMachines[nextState.activeTimeMachineID] diff --git a/ui/src/timeMachine/reducers/index.ts b/ui/src/timeMachine/reducers/index.ts index 29f385e0c0..68c0ad6d83 100644 --- a/ui/src/timeMachine/reducers/index.ts +++ b/ui/src/timeMachine/reducers/index.ts @@ -8,10 +8,7 @@ import {createView, defaultViewQuery} from 'src/shared/utils/view' import {isConfigValid, buildQuery} from 'src/timeMachine/utils/queryBuilder' // Constants -import { - VEO_TIME_MACHINE_ID, - DE_TIME_MACHINE_ID, -} from 'src/timeMachine/constants' +import {TimeMachineEnum} from 'src/timeMachine/constants' import {AUTOREFRESH_DEFAULT} from 'src/shared/constants' import { THRESHOLD_TYPE_TEXT, @@ -71,9 +68,11 @@ export interface TimeMachineState { } export interface TimeMachinesState { - activeTimeMachineID: string + activeTimeMachineID: TimeMachineEnum timeMachines: { - [timeMachineID: string]: TimeMachineState + [TimeMachineEnum.DE]: TimeMachineState + [TimeMachineEnum.VEO]: TimeMachineState + [TimeMachineEnum.Alerting]: TimeMachineState } } @@ -105,10 +104,11 @@ export const initialStateHelper = (): TimeMachineState => ({ }) export const initialState = (): TimeMachinesState => ({ - activeTimeMachineID: DE_TIME_MACHINE_ID, + activeTimeMachineID: TimeMachineEnum.DE, timeMachines: { - [VEO_TIME_MACHINE_ID]: initialStateHelper(), - [DE_TIME_MACHINE_ID]: initialStateHelper(), + [TimeMachineEnum.VEO]: initialStateHelper(), + [TimeMachineEnum.DE]: initialStateHelper(), + [TimeMachineEnum.Alerting]: initialStateHelper(), }, })