feat: Alerting add alert builder veo state (#14499)
* Define new check, edit check and check view routes with VEO Co-authored-by: Michael Desa <mjdesa@gmail.com> * Add task status to other task types * Put editAlerting route behind feature flag * add action and reducer for update current check * Add init edit and new check editor overlay * Split VEO in to two for new and edit view * get edit and new CheckEO's ready * Create getViewForTimeMachine action * current check should be a partial check * Fix view typing * Fix linter errors * Fix equality * Catch save VEO errorspull/14500/head
parent
93649a71b5
commit
bbc37b4c68
|
@ -8652,12 +8652,7 @@ components:
|
||||||
description: The name of the organization that owns this Task.
|
description: The name of the organization that owns this Task.
|
||||||
type: string
|
type: string
|
||||||
status:
|
status:
|
||||||
description: Starting state of the task. 'inactive' tasks are not run until they are updated to 'active'
|
$ref: "#/components/schemas/TaskStatusType"
|
||||||
default: active
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- active
|
|
||||||
- inactive
|
|
||||||
flux:
|
flux:
|
||||||
description: The Flux script to run for this task.
|
description: The Flux script to run for this task.
|
||||||
type: string
|
type: string
|
||||||
|
@ -8669,12 +8664,7 @@ components:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
description: Starting state of the task. 'inactive' tasks are not run until they are updated to 'active'
|
$ref: "#/components/schemas/TaskStatusType"
|
||||||
default: active
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- active
|
|
||||||
- inactive
|
|
||||||
flux:
|
flux:
|
||||||
description: The Flux script to run for this task.
|
description: The Flux script to run for this task.
|
||||||
type: string
|
type: string
|
||||||
|
|
|
@ -20,6 +20,7 @@ export type Action =
|
||||||
| ReturnType<typeof setCheck>
|
| ReturnType<typeof setCheck>
|
||||||
| ReturnType<typeof removeCheck>
|
| ReturnType<typeof removeCheck>
|
||||||
| ReturnType<typeof setCurrentCheck>
|
| ReturnType<typeof setCurrentCheck>
|
||||||
|
| ReturnType<typeof updateCurrentCheck>
|
||||||
|
|
||||||
export const setAllChecks = (status: RemoteDataState, checks?: Check[]) => ({
|
export const setAllChecks = (status: RemoteDataState, checks?: Check[]) => ({
|
||||||
type: 'SET_ALL_CHECKS' as 'SET_ALL_CHECKS',
|
type: 'SET_ALL_CHECKS' as 'SET_ALL_CHECKS',
|
||||||
|
@ -36,11 +37,19 @@ export const removeCheck = (checkID: string) => ({
|
||||||
payload: {checkID},
|
payload: {checkID},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const setCurrentCheck = (status: RemoteDataState, check?: Check) => ({
|
export const setCurrentCheck = (
|
||||||
|
status: RemoteDataState,
|
||||||
|
check?: Partial<Check>
|
||||||
|
) => ({
|
||||||
type: 'SET_CURRENT_CHECK' as 'SET_CURRENT_CHECK',
|
type: 'SET_CURRENT_CHECK' as 'SET_CURRENT_CHECK',
|
||||||
payload: {status, check},
|
payload: {status, check},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const updateCurrentCheck = (checkUpdate: Partial<Check>) => ({
|
||||||
|
type: 'UPDATE_CURRENT_CHECK' as 'UPDATE_CURRENT_CHECK',
|
||||||
|
payload: {status, checkUpdate},
|
||||||
|
})
|
||||||
|
|
||||||
export const getChecks = () => async (
|
export const getChecks = () => async (
|
||||||
dispatch: Dispatch<Action | NotificationAction>,
|
dispatch: Dispatch<Action | NotificationAction>,
|
||||||
getState: GetState
|
getState: GetState
|
||||||
|
|
|
@ -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<Check>
|
||||||
|
status: RemoteDataState
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = WithRouterProps & DispatchProps & StateProps
|
||||||
|
|
||||||
|
const EditCheckEditorOverlay: FunctionComponent<Props> = ({
|
||||||
|
onSetActiveTimeMachine,
|
||||||
|
params,
|
||||||
|
check,
|
||||||
|
status,
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
getCurrentCheck(params.checkID)
|
||||||
|
onSetActiveTimeMachine(TimeMachineEnum.Alerting)
|
||||||
|
}, [params.checkID])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// create view properties from check
|
||||||
|
const view = createView<XYView>(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 (
|
||||||
|
<Overlay visible={true} className="veo-overlay">
|
||||||
|
<div className="veo">
|
||||||
|
<SpinnerContainer
|
||||||
|
spinnerComponent={<TechnoSpinner />}
|
||||||
|
loading={status || RemoteDataState.Loading}
|
||||||
|
>
|
||||||
|
<VEOHeader
|
||||||
|
key={check && check.name}
|
||||||
|
name={check && check.name}
|
||||||
|
onSetName={handleUpdateName}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onSave={handleSave}
|
||||||
|
/>
|
||||||
|
<div className="veo-contents">
|
||||||
|
<TimeMachine />
|
||||||
|
</div>
|
||||||
|
</SpinnerContainer>
|
||||||
|
</div>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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<StateProps, DispatchProps, {}>(
|
||||||
|
mstp,
|
||||||
|
mdtp
|
||||||
|
)(withRouter(EditCheckEditorOverlay))
|
|
@ -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<Check>
|
||||||
|
status: RemoteDataState
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = DispatchProps & StateProps
|
||||||
|
|
||||||
|
const NewCheckOverlay: FunctionComponent<Props> = ({
|
||||||
|
onSetActiveTimeMachine,
|
||||||
|
updateCurrentCheck,
|
||||||
|
setCurrentCheck,
|
||||||
|
status,
|
||||||
|
check,
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentCheck(RemoteDataState.Done, DEFAULT_CHECK)
|
||||||
|
const view = createView<XYView>(ViewType.XY)
|
||||||
|
onSetActiveTimeMachine(TimeMachineEnum.Alerting, {view})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleUpdateName = (name: string) => {
|
||||||
|
updateCurrentCheck({name})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {}
|
||||||
|
|
||||||
|
const handleSave = () => {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Overlay visible={true} className="veo-overlay">
|
||||||
|
<div className="veo">
|
||||||
|
<SpinnerContainer
|
||||||
|
spinnerComponent={<TechnoSpinner />}
|
||||||
|
loading={status || RemoteDataState.Loading}
|
||||||
|
>
|
||||||
|
<VEOHeader
|
||||||
|
key={check && check.name}
|
||||||
|
name={check && check.name}
|
||||||
|
onSetName={handleUpdateName}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onSave={handleSave}
|
||||||
|
/>
|
||||||
|
<div className="veo-contents">
|
||||||
|
<TimeMachine />
|
||||||
|
</div>
|
||||||
|
</SpinnerContainer>
|
||||||
|
</div>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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<StateProps, DispatchProps, {}>(
|
||||||
|
mstp,
|
||||||
|
mdtp
|
||||||
|
)(NewCheckOverlay)
|
|
@ -9,11 +9,19 @@ import {
|
||||||
NotificationRuleType,
|
NotificationRuleType,
|
||||||
CheckStatusLevel,
|
CheckStatusLevel,
|
||||||
ThresholdType,
|
ThresholdType,
|
||||||
|
ThresholdCheck,
|
||||||
} from 'src/types'
|
} from 'src/types'
|
||||||
|
|
||||||
export const DEFAULT_CHECK_NAME = 'Name this check'
|
export const DEFAULT_CHECK_NAME = 'Name this check'
|
||||||
export const DEFAULT_NOTIFICATION_RULE_NAME = 'Name this notification rule'
|
export const DEFAULT_NOTIFICATION_RULE_NAME = 'Name this notification rule'
|
||||||
|
|
||||||
|
export const DEFAULT_CHECK: Partial<ThresholdCheck> = {
|
||||||
|
name: DEFAULT_CHECK_NAME,
|
||||||
|
type: CheckType.Threshold,
|
||||||
|
status: CheckBase.StatusEnum.Active,
|
||||||
|
thresholds: [],
|
||||||
|
}
|
||||||
|
|
||||||
export const query: DashboardQuery = {
|
export const query: DashboardQuery = {
|
||||||
text: 'this is query',
|
text: 'this is query',
|
||||||
editMode: QueryEditMode.Advanced,
|
editMode: QueryEditMode.Advanced,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {Action} from 'src/alerting/actions/checks'
|
||||||
export interface ChecksState {
|
export interface ChecksState {
|
||||||
status: RemoteDataState
|
status: RemoteDataState
|
||||||
list: Check[]
|
list: Check[]
|
||||||
current: {status: RemoteDataState; check: Check}
|
current: {status: RemoteDataState; check: Partial<Check>}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultChecksState: ChecksState = {
|
export const defaultChecksState: ChecksState = {
|
||||||
|
@ -52,6 +52,13 @@ export default (
|
||||||
if (action.payload.check) {
|
if (action.payload.check) {
|
||||||
draftState.current.check = 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
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -336,13 +336,13 @@ export const deleteDashboardAsync = (dashboard: Dashboard) => async (
|
||||||
}
|
}
|
||||||
|
|
||||||
export const refreshDashboardVariableValues = (
|
export const refreshDashboardVariableValues = (
|
||||||
dashboard: Dashboard,
|
dashboardID: string,
|
||||||
nextViews: View[]
|
nextViews: View[]
|
||||||
) => (dispatch, getState: GetState) => {
|
) => (dispatch, getState: GetState) => {
|
||||||
const variables = extractVariablesList(getState())
|
const variables = extractVariablesList(getState())
|
||||||
const variablesInUse = filterUnusedVars(variables, nextViews)
|
const variablesInUse = filterUnusedVars(variables, nextViews)
|
||||||
|
|
||||||
return dispatch(refreshVariableValues(dashboard.id, variablesInUse))
|
return dispatch(refreshVariableValues(dashboardID, variablesInUse))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDashboardAsync = (dashboardID: string) => async (
|
export const getDashboardAsync = (dashboardID: string) => async (
|
||||||
|
@ -363,7 +363,7 @@ export const getDashboardAsync = (dashboardID: string) => async (
|
||||||
dispatch(setViews(RemoteDataState.Done, views))
|
dispatch(setViews(RemoteDataState.Done, views))
|
||||||
|
|
||||||
// Ensure the values for the variables in use on the dashboard are populated
|
// 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
|
// Now that all the necessary state has been loaded, set the dashboard
|
||||||
dispatch(setDashboard(dashboard))
|
dispatch(setDashboard(dashboard))
|
||||||
|
@ -390,18 +390,24 @@ export const updateDashboardAsync = (dashboard: Dashboard) => async (
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createCellWithView = (
|
export const createCellWithView = (
|
||||||
dashboard: Dashboard,
|
dashboardID: string,
|
||||||
view: NewView,
|
view: NewView,
|
||||||
clonedCell?: Cell
|
clonedCell?: Cell
|
||||||
) => async (dispatch, getState: GetState): Promise<void> => {
|
) => async (dispatch, getState: GetState): Promise<void> => {
|
||||||
try {
|
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)
|
const cell: CreateCell = getNewDashboardCell(dashboard, clonedCell)
|
||||||
|
|
||||||
// Create the cell
|
// 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
|
// 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
|
// Update the dashboard with the new cell
|
||||||
let updatedDashboard: Dashboard = {
|
let updatedDashboard: Dashboard = {
|
||||||
|
@ -412,9 +418,9 @@ export const createCellWithView = (
|
||||||
updatedDashboard = await updateDashboardAJAX(dashboard)
|
updatedDashboard = await updateDashboardAJAX(dashboard)
|
||||||
|
|
||||||
// Refresh variables in use on 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(setView(createdCell.id, newView, RemoteDataState.Done))
|
||||||
dispatch(editDashboard(updatedDashboard))
|
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,
|
dispatch,
|
||||||
getState: GetState
|
getState: GetState
|
||||||
) => {
|
) => {
|
||||||
const cellID = view.cellID
|
const cellID = view.cellID
|
||||||
|
|
||||||
try {
|
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)
|
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))
|
dispatch(setView(cellID, newView, RemoteDataState.Done))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -473,7 +479,7 @@ export const deleteCellAsync = (dashboard: Dashboard, cell: Cell) => async (
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
deleteCellAJAX(dashboard.id, cell),
|
deleteCellAJAX(dashboard.id, cell),
|
||||||
dispatch(refreshDashboardVariableValues(dashboard, views)),
|
dispatch(refreshDashboardVariableValues(dashboard.id, views)),
|
||||||
])
|
])
|
||||||
|
|
||||||
dispatch(removeCell(dashboard, cell))
|
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,
|
dispatch,
|
||||||
getState: GetState
|
getState: GetState
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
|
@ -585,12 +591,13 @@ export const saveVEOView = (dashboard: Dashboard) => async (
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (view.id) {
|
if (view.id) {
|
||||||
await dispatch(updateView(dashboard, view))
|
await dispatch(updateView(dashboardID, view))
|
||||||
} else {
|
} else {
|
||||||
await dispatch(createCellWithView(dashboard, view))
|
await dispatch(createCellWithView(dashboardID, view))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
dispatch(notify(copy.cellAddFailed()))
|
dispatch(notify(copy.cellAddFailed()))
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ export const createNoteCell = (dashboardID: string) => async (
|
||||||
|
|
||||||
view.properties.note = note
|
view.properties.note = note
|
||||||
|
|
||||||
return dispatch(createCellWithView(dashboard, view))
|
return dispatch(createCellWithView(dashboard.id, view))
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResetNoteStateAction {
|
export interface ResetNoteStateAction {
|
||||||
|
|
|
@ -5,9 +5,14 @@ import {
|
||||||
} from 'src/dashboards/apis/'
|
} from 'src/dashboards/apis/'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {RemoteDataState} from 'src/types'
|
import {RemoteDataState, QueryView} from 'src/types'
|
||||||
import {Dispatch} from 'redux'
|
import {Dispatch} from 'redux'
|
||||||
import {View} from 'src/types'
|
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
|
export type Action = SetViewAction | SetViewsAction | ResetViewsAction
|
||||||
|
|
||||||
|
@ -83,3 +88,19 @@ export const updateView = (dashboardID: string, view: View) => async (
|
||||||
dispatch(setView(viewID, null, RemoteDataState.Error))
|
dispatch(setView(viewID, null, RemoteDataState.Error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getViewForTimeMachine = (
|
||||||
|
dashboardID: string,
|
||||||
|
cellID: string,
|
||||||
|
timeMachineID: TimeMachineEnum
|
||||||
|
) => async (dispatch: Dispatch<Action | TimeMachineAction>): Promise<void> => {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import {
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
|
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
|
||||||
import {createView} from 'src/shared/utils/view'
|
|
||||||
import {
|
import {
|
||||||
extractRateLimitResourceName,
|
extractRateLimitResourceName,
|
||||||
extractRateLimitStatus,
|
extractRateLimitStatus,
|
||||||
|
@ -38,7 +37,6 @@ import {
|
||||||
DASHBOARD_LAYOUT_ROW_HEIGHT,
|
DASHBOARD_LAYOUT_ROW_HEIGHT,
|
||||||
AUTOREFRESH_DEFAULT,
|
AUTOREFRESH_DEFAULT,
|
||||||
} from 'src/shared/constants'
|
} from 'src/shared/constants'
|
||||||
import {VEO_TIME_MACHINE_ID} from 'src/timeMachine/constants'
|
|
||||||
import {DEFAULT_TIME_RANGE} from 'src/shared/constants/timeRanges'
|
import {DEFAULT_TIME_RANGE} from 'src/shared/constants/timeRanges'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
@ -51,9 +49,6 @@ import {
|
||||||
AppState,
|
AppState,
|
||||||
AutoRefresh,
|
AutoRefresh,
|
||||||
AutoRefreshStatus,
|
AutoRefreshStatus,
|
||||||
XYView,
|
|
||||||
ViewType,
|
|
||||||
QueryView,
|
|
||||||
} from 'src/types'
|
} from 'src/types'
|
||||||
import {RemoteDataState} from 'src/types'
|
import {RemoteDataState} from 'src/types'
|
||||||
import {WithRouterProps} from 'react-router'
|
import {WithRouterProps} from 'react-router'
|
||||||
|
@ -299,7 +294,8 @@ class DashboardPage extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleAddCell = async (): Promise<void> => {
|
private handleAddCell = async (): Promise<void> => {
|
||||||
this.showVEO()
|
const {router, location} = this.props
|
||||||
|
router.push(`${location.pathname}/cells/new`)
|
||||||
}
|
}
|
||||||
|
|
||||||
private showNoteOverlay = async (id?: string): Promise<void> => {
|
private showNoteOverlay = async (id?: string): Promise<void> => {
|
||||||
|
@ -311,27 +307,15 @@ class DashboardPage extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleEditView = (cellID: string): void => {
|
private handleEditView = (cellID: string): void => {
|
||||||
this.showVEO(cellID)
|
const {router, location} = this.props
|
||||||
}
|
router.push(`${location.pathname}/cells/${cellID}/edit`)
|
||||||
|
|
||||||
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<XYView>(ViewType.XY)
|
|
||||||
onSetActiveTimeMachine(VEO_TIME_MACHINE_ID, {view})
|
|
||||||
router.push(`${location.pathname}/cells/new`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleCloneCell = async (cell: Cell): Promise<void> => {
|
private handleCloneCell = async (cell: Cell): Promise<void> => {
|
||||||
const {dashboard, onCreateCellWithView, views} = this.props
|
const {dashboard, onCreateCellWithView, views} = this.props
|
||||||
const viewEntry = views[cell.id]
|
const viewEntry = views[cell.id]
|
||||||
if (viewEntry && viewEntry.view) {
|
if (viewEntry && viewEntry.view) {
|
||||||
await onCreateCellWithView(dashboard, viewEntry.view, cell)
|
await onCreateCellWithView(dashboard.id, viewEntry.view, cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<Props> = ({
|
||||||
|
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 (
|
||||||
|
<Overlay visible={true} className="veo-overlay">
|
||||||
|
<div className="veo">
|
||||||
|
<SpinnerContainer
|
||||||
|
spinnerComponent={<TechnoSpinner />}
|
||||||
|
loading={loadingState}
|
||||||
|
>
|
||||||
|
<VEOHeader
|
||||||
|
key={view && view.name}
|
||||||
|
name={view && view.name}
|
||||||
|
onSetName={onSetName}
|
||||||
|
onCancel={handleClose}
|
||||||
|
onSave={handleSave}
|
||||||
|
/>
|
||||||
|
<div className="veo-contents">
|
||||||
|
<TimeMachine />
|
||||||
|
</div>
|
||||||
|
</SpinnerContainer>
|
||||||
|
</div>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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<StateProps, DispatchProps, {}>(
|
||||||
|
mstp,
|
||||||
|
mdtp
|
||||||
|
)(withRouter(NewViewVEO))
|
|
@ -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<Props> = ({
|
||||||
|
onSetActiveTimeMachine,
|
||||||
|
loadingState,
|
||||||
|
onSaveView,
|
||||||
|
onSetName,
|
||||||
|
params,
|
||||||
|
router,
|
||||||
|
view,
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const view = createView<XYView>(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 (
|
||||||
|
<Overlay visible={true} className="veo-overlay">
|
||||||
|
<div className="veo">
|
||||||
|
<SpinnerContainer
|
||||||
|
spinnerComponent={<TechnoSpinner />}
|
||||||
|
loading={loadingState}
|
||||||
|
>
|
||||||
|
<VEOHeader
|
||||||
|
key={view && view.name}
|
||||||
|
name={view && view.name}
|
||||||
|
onSetName={onSetName}
|
||||||
|
onCancel={handleClose}
|
||||||
|
onSave={handleSave}
|
||||||
|
/>
|
||||||
|
<div className="veo-contents">
|
||||||
|
<TimeMachine />
|
||||||
|
</div>
|
||||||
|
</SpinnerContainer>
|
||||||
|
</div>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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<StateProps, DispatchProps, {}>(
|
||||||
|
mstp,
|
||||||
|
mdtp
|
||||||
|
)(withRouter(NewViewVEO))
|
|
@ -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<Props> {
|
|
||||||
public render() {
|
|
||||||
const {params} = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Overlay visible={true} className="veo-overlay">
|
|
||||||
<div className="veo">
|
|
||||||
<SpinnerContainer
|
|
||||||
spinnerComponent={<TechnoSpinner />}
|
|
||||||
loading={this.loading}
|
|
||||||
>
|
|
||||||
<VEOContents
|
|
||||||
dashboardID={params.dashboardID}
|
|
||||||
onClose={this.handleClose}
|
|
||||||
/>
|
|
||||||
</SpinnerContainer>
|
|
||||||
</div>
|
|
||||||
</Overlay>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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<XYView>(ViewType.XY)
|
|
||||||
return {view, viewsStatus: status}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mdtp: DispatchProps = {
|
|
||||||
onSetActiveTimeMachine: setActiveTimeMachine,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mstp,
|
|
||||||
mdtp
|
|
||||||
)(withRouter<OwnProps, {}>(VEO))
|
|
|
@ -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<Props, {}> {
|
|
||||||
public componentDidMount() {
|
|
||||||
this.props.executeQueries()
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const {name, onSetName} = this.props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<VEOHeader
|
|
||||||
key={name}
|
|
||||||
name={name}
|
|
||||||
onSetName={onSetName}
|
|
||||||
onCancel={this.props.onClose}
|
|
||||||
onSave={this.handleSave}
|
|
||||||
/>
|
|
||||||
<div className="veo-contents">
|
|
||||||
<TimeMachine />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleSave = async (): Promise<void> => {
|
|
||||||
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<StateProps, DispatchProps, OwnProps>(
|
|
||||||
mstp,
|
|
||||||
mdtp
|
|
||||||
)(VEOContents)
|
|
|
@ -11,7 +11,7 @@ import AssetLimitAlert from 'src/cloud/components/AssetLimitAlert'
|
||||||
import {setActiveTimeMachine} from 'src/timeMachine/actions'
|
import {setActiveTimeMachine} from 'src/timeMachine/actions'
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {DE_TIME_MACHINE_ID} from 'src/timeMachine/constants'
|
import {TimeMachineEnum} from 'src/timeMachine/constants'
|
||||||
import {HoverTimeProvider} from 'src/dashboards/utils/hoverTime'
|
import {HoverTimeProvider} from 'src/dashboards/utils/hoverTime'
|
||||||
import {queryBuilderFetcher} from 'src/timeMachine/apis/QueryBuilderFetcher'
|
import {queryBuilderFetcher} from 'src/timeMachine/apis/QueryBuilderFetcher'
|
||||||
import {
|
import {
|
||||||
|
@ -37,7 +37,7 @@ class DataExplorer extends PureComponent<Props, {}> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
props.onSetActiveTimeMachine(DE_TIME_MACHINE_ID)
|
props.onSetActiveTimeMachine(TimeMachineEnum.DE)
|
||||||
queryBuilderFetcher.clearCache()
|
queryBuilderFetcher.clearCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ class SaveAsCellForm extends PureComponent<Props, State> {
|
||||||
} else {
|
} else {
|
||||||
const selectedDashboard = dashboards.find(d => d.id === dashID)
|
const selectedDashboard = dashboards.find(d => d.id === dashID)
|
||||||
targetDashboardName = selectedDashboard.name
|
targetDashboardName = selectedDashboard.name
|
||||||
onCreateCellWithView(selectedDashboard, viewWithProps)
|
onCreateCellWithView(selectedDashboard.id, viewWithProps)
|
||||||
}
|
}
|
||||||
notify(cellAdded(cellName, targetDashboardName))
|
notify(cellAdded(cellName, targetDashboardName))
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -195,7 +195,7 @@ class SaveAsCellForm extends PureComponent<Props, State> {
|
||||||
cells: [],
|
cells: [],
|
||||||
}
|
}
|
||||||
const dashboard = await createDashboard(newDashboard)
|
const dashboard = await createDashboard(newDashboard)
|
||||||
onCreateCellWithView(dashboard, view)
|
onCreateCellWithView(dashboard.id, view)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,8 @@ import GetMe from 'src/shared/containers/GetMe'
|
||||||
import Notifications from 'src/shared/containers/Notifications'
|
import Notifications from 'src/shared/containers/Notifications'
|
||||||
import TaskExportOverlay from 'src/tasks/components/TaskExportOverlay'
|
import TaskExportOverlay from 'src/tasks/components/TaskExportOverlay'
|
||||||
import TaskImportOverlay from 'src/tasks/components/TaskImportOverlay'
|
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 NoteEditorOverlay from 'src/dashboards/components/NoteEditorOverlay'
|
||||||
import OnboardingWizardPage from 'src/onboarding/containers/OnboardingWizardPage'
|
import OnboardingWizardPage from 'src/onboarding/containers/OnboardingWizardPage'
|
||||||
import BucketsIndex from 'src/buckets/containers/BucketsIndex'
|
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 AlertHistoryIndex from 'src/alerting/containers/AlertHistoryIndex'
|
||||||
import BucketsDeleteDataOverlay from 'src/shared/components/DeleteDataOverlay'
|
import BucketsDeleteDataOverlay from 'src/shared/components/DeleteDataOverlay'
|
||||||
import DEDeleteDataOverlay from 'src/dataExplorer/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'
|
import {FeatureFlag} from 'src/shared/utils/featureFlag'
|
||||||
|
|
||||||
|
@ -195,8 +198,8 @@ class Root extends PureComponent {
|
||||||
component={DashboardPage}
|
component={DashboardPage}
|
||||||
>
|
>
|
||||||
<Route path="cells">
|
<Route path="cells">
|
||||||
<Route path="new" component={VEO} />
|
<Route path="new" component={NewVEO} />
|
||||||
<Route path=":cellID/edit" component={VEO} />
|
<Route path=":cellID/edit" component={EditVEO} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="notes">
|
<Route path="notes">
|
||||||
<Route path="new" component={NoteEditorOverlay} />
|
<Route path="new" component={NoteEditorOverlay} />
|
||||||
|
@ -313,7 +316,13 @@ class Root extends PureComponent {
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<FeatureFlag name="alerting">
|
<FeatureFlag name="alerting">
|
||||||
<Route path="alerting" component={AlertingIndex} />
|
<Route path="alerting" component={AlertingIndex}>
|
||||||
|
<Route path="checks/new" component={NewCheckEO} />
|
||||||
|
<Route
|
||||||
|
path="checks/:checkID/edit"
|
||||||
|
component={EditCheckEO}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="alert-history"
|
path="alert-history"
|
||||||
component={AlertHistoryIndex}
|
component={AlertHistoryIndex}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
} from 'src/types'
|
} from 'src/types'
|
||||||
import {Color} from 'src/types/colors'
|
import {Color} from 'src/types/colors'
|
||||||
import {HistogramPosition} from '@influxdata/giraffe'
|
import {HistogramPosition} from '@influxdata/giraffe'
|
||||||
|
import {TimeMachineEnum} from 'src/timeMachine/constants'
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
| QueryBuilderAction
|
| QueryBuilderAction
|
||||||
|
@ -76,13 +77,13 @@ export type Action =
|
||||||
interface SetActiveTimeMachineAction {
|
interface SetActiveTimeMachineAction {
|
||||||
type: 'SET_ACTIVE_TIME_MACHINE'
|
type: 'SET_ACTIVE_TIME_MACHINE'
|
||||||
payload: {
|
payload: {
|
||||||
activeTimeMachineID: string
|
activeTimeMachineID: TimeMachineEnum
|
||||||
initialState: Partial<TimeMachineState>
|
initialState: Partial<TimeMachineState>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setActiveTimeMachine = (
|
export const setActiveTimeMachine = (
|
||||||
activeTimeMachineID: string,
|
activeTimeMachineID: TimeMachineEnum,
|
||||||
initialState: Partial<TimeMachineState> = {}
|
initialState: Partial<TimeMachineState> = {}
|
||||||
): SetActiveTimeMachineAction => ({
|
): SetActiveTimeMachineAction => ({
|
||||||
type: 'SET_ACTIVE_TIME_MACHINE',
|
type: 'SET_ACTIVE_TIME_MACHINE',
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
export const DE_TIME_MACHINE_ID = 'de'
|
export enum TimeMachineEnum {
|
||||||
export const VEO_TIME_MACHINE_ID = 'veo'
|
DE = 'de',
|
||||||
|
VEO = 'veo',
|
||||||
|
Alerting = 'alerting',
|
||||||
|
}
|
||||||
|
|
|
@ -26,10 +26,7 @@ import {
|
||||||
import {createView} from 'src/shared/utils/view'
|
import {createView} from 'src/shared/utils/view'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {
|
import {TimeMachineEnum} from 'src/timeMachine/constants'
|
||||||
DE_TIME_MACHINE_ID,
|
|
||||||
VEO_TIME_MACHINE_ID,
|
|
||||||
} from 'src/timeMachine/constants'
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {TimeMachineTab} from 'src/types/timeMachine'
|
import {TimeMachineTab} from 'src/types/timeMachine'
|
||||||
|
@ -43,10 +40,10 @@ import {selectAggregateWindow} from '../actions/queryBuilder'
|
||||||
describe('timeMachinesReducer', () => {
|
describe('timeMachinesReducer', () => {
|
||||||
test('it directs actions to the currently active timeMachine', () => {
|
test('it directs actions to the currently active timeMachine', () => {
|
||||||
const state = initialState()
|
const state = initialState()
|
||||||
const de = state.timeMachines[DE_TIME_MACHINE_ID]
|
const de = state.timeMachines[TimeMachineEnum.DE]
|
||||||
const veo = state.timeMachines[VEO_TIME_MACHINE_ID]
|
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(de.activeTab).toEqual(TimeMachineTab.Queries)
|
||||||
expect(veo.activeTab).toEqual(TimeMachineTab.Queries)
|
expect(veo.activeTab).toEqual(TimeMachineTab.Queries)
|
||||||
|
|
||||||
|
@ -55,8 +52,8 @@ describe('timeMachinesReducer', () => {
|
||||||
setActiveTab(TimeMachineTab.Visualization)
|
setActiveTab(TimeMachineTab.Visualization)
|
||||||
)
|
)
|
||||||
|
|
||||||
const nextDE = nextState.timeMachines[DE_TIME_MACHINE_ID]
|
const nextDE = nextState.timeMachines[TimeMachineEnum.DE]
|
||||||
const nextVEO = nextState.timeMachines[VEO_TIME_MACHINE_ID]
|
const nextVEO = nextState.timeMachines[TimeMachineEnum.VEO]
|
||||||
|
|
||||||
expect(nextDE.activeTab).toEqual(TimeMachineTab.Visualization)
|
expect(nextDE.activeTab).toEqual(TimeMachineTab.Visualization)
|
||||||
expect(nextVEO.activeTab).toEqual(TimeMachineTab.Queries)
|
expect(nextVEO.activeTab).toEqual(TimeMachineTab.Queries)
|
||||||
|
@ -65,7 +62,7 @@ describe('timeMachinesReducer', () => {
|
||||||
test('it resets tab and draftScript state on a timeMachine when activated', () => {
|
test('it resets tab and draftScript state on a timeMachine when activated', () => {
|
||||||
const state = initialState()
|
const state = initialState()
|
||||||
|
|
||||||
expect(state.activeTimeMachineID).toEqual(DE_TIME_MACHINE_ID)
|
expect(state.activeTimeMachineID).toEqual(TimeMachineEnum.DE)
|
||||||
|
|
||||||
const activeTimeMachine = state.timeMachines[state.activeTimeMachineID]
|
const activeTimeMachine = state.timeMachines[state.activeTimeMachineID]
|
||||||
|
|
||||||
|
@ -100,10 +97,10 @@ describe('timeMachinesReducer', () => {
|
||||||
|
|
||||||
const nextState = timeMachinesReducer(
|
const nextState = timeMachinesReducer(
|
||||||
state,
|
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 =
|
const nextTimeMachine =
|
||||||
nextState.timeMachines[nextState.activeTimeMachineID]
|
nextState.timeMachines[nextState.activeTimeMachineID]
|
||||||
|
|
|
@ -8,10 +8,7 @@ import {createView, defaultViewQuery} from 'src/shared/utils/view'
|
||||||
import {isConfigValid, buildQuery} from 'src/timeMachine/utils/queryBuilder'
|
import {isConfigValid, buildQuery} from 'src/timeMachine/utils/queryBuilder'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {
|
import {TimeMachineEnum} from 'src/timeMachine/constants'
|
||||||
VEO_TIME_MACHINE_ID,
|
|
||||||
DE_TIME_MACHINE_ID,
|
|
||||||
} from 'src/timeMachine/constants'
|
|
||||||
import {AUTOREFRESH_DEFAULT} from 'src/shared/constants'
|
import {AUTOREFRESH_DEFAULT} from 'src/shared/constants'
|
||||||
import {
|
import {
|
||||||
THRESHOLD_TYPE_TEXT,
|
THRESHOLD_TYPE_TEXT,
|
||||||
|
@ -71,9 +68,11 @@ export interface TimeMachineState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TimeMachinesState {
|
export interface TimeMachinesState {
|
||||||
activeTimeMachineID: string
|
activeTimeMachineID: TimeMachineEnum
|
||||||
timeMachines: {
|
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 => ({
|
export const initialState = (): TimeMachinesState => ({
|
||||||
activeTimeMachineID: DE_TIME_MACHINE_ID,
|
activeTimeMachineID: TimeMachineEnum.DE,
|
||||||
timeMachines: {
|
timeMachines: {
|
||||||
[VEO_TIME_MACHINE_ID]: initialStateHelper(),
|
[TimeMachineEnum.VEO]: initialStateHelper(),
|
||||||
[DE_TIME_MACHINE_ID]: initialStateHelper(),
|
[TimeMachineEnum.DE]: initialStateHelper(),
|
||||||
|
[TimeMachineEnum.Alerting]: initialStateHelper(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue