Merge pull request #3739 from influxdata/fun/dashboard_page

Convert DashboardPage to TypeScript & introduce improved file structure for types
pull/10616/head
Jared Scheib 2018-06-25 17:23:39 -07:00 committed by GitHub
commit f4ab45d420
79 changed files with 1649 additions and 1133 deletions

View File

@ -1,205 +1,113 @@
import {Cell} from 'src/types'
import {CellType, ThresholdType} from 'src/types/dashboard'
import {ColorNumber, ColorString} from 'src/types/colors'
import {
Axes,
DecimalPlaces,
FieldOption,
TableOptions,
} from 'src/types/dashboard'
import * as CellEditorOverlayActions from 'src/types/actions/cellEditorOverlay'
import * as ColorsModels from 'src/types/colors'
import * as DashboardsModels from 'src/types/dashboards'
export type Action =
| ShowCellEditorOverlayAction
| HideCellEditorOverlayAction
| ChangeCellTypeAction
| RenameCellAction
| UpdateThresholdsListColorsAction
| UpdateThresholdsListTypeAction
| UpdateGaugeColorsAction
| UpdateAxesAction
| UpdateTableOptionsAction
| UpdateLineColorsAction
| ChangeTimeFormatAction
| ChangeDecimalPlacesAction
| UpdateFieldOptionsAction
interface ShowCellEditorOverlayAction {
type: 'SHOW_CELL_EDITOR_OVERLAY'
payload: {
cell: Cell
}
}
export const showCellEditorOverlay = (
cell: Cell
): ShowCellEditorOverlayAction => ({
export const showCellEditorOverlay: CellEditorOverlayActions.ShowCellEditorOverlayActionCreator = (
cell: DashboardsModels.Cell
): CellEditorOverlayActions.ShowCellEditorOverlayAction => ({
type: 'SHOW_CELL_EDITOR_OVERLAY',
payload: {
cell,
},
})
interface HideCellEditorOverlayAction {
type: 'HIDE_CELL_EDITOR_OVERLAY'
}
export const hideCellEditorOverlay = (): HideCellEditorOverlayAction => ({
export const hideCellEditorOverlay = (): CellEditorOverlayActions.HideCellEditorOverlayAction => ({
type: 'HIDE_CELL_EDITOR_OVERLAY',
})
interface ChangeCellTypeAction {
type: 'CHANGE_CELL_TYPE'
payload: {
cellType: CellType
}
}
export const changeCellType = (cellType: CellType): ChangeCellTypeAction => ({
export const changeCellType = (
cellType: DashboardsModels.CellType
): CellEditorOverlayActions.ChangeCellTypeAction => ({
type: 'CHANGE_CELL_TYPE',
payload: {
cellType,
},
})
interface RenameCellAction {
type: 'RENAME_CELL'
payload: {
cellName: string
}
}
export const renameCell = (cellName: string): RenameCellAction => ({
export const renameCell = (
cellName: string
): CellEditorOverlayActions.RenameCellAction => ({
type: 'RENAME_CELL',
payload: {
cellName,
},
})
interface UpdateThresholdsListColorsAction {
type: 'UPDATE_THRESHOLDS_LIST_COLORS'
payload: {
thresholdsListColors: ColorNumber[]
}
}
export const updateThresholdsListColors = (
thresholdsListColors: ColorNumber[]
): UpdateThresholdsListColorsAction => ({
thresholdsListColors: ColorsModels.ColorNumber[]
): CellEditorOverlayActions.UpdateThresholdsListColorsAction => ({
type: 'UPDATE_THRESHOLDS_LIST_COLORS',
payload: {
thresholdsListColors,
},
})
interface UpdateThresholdsListTypeAction {
type: 'UPDATE_THRESHOLDS_LIST_TYPE'
payload: {
thresholdsListType: ThresholdType
}
}
export const updateThresholdsListType = (
thresholdsListType: ThresholdType
): UpdateThresholdsListTypeAction => ({
thresholdsListType: DashboardsModels.ThresholdType
): CellEditorOverlayActions.UpdateThresholdsListTypeAction => ({
type: 'UPDATE_THRESHOLDS_LIST_TYPE',
payload: {
thresholdsListType,
},
})
interface UpdateGaugeColorsAction {
type: 'UPDATE_GAUGE_COLORS'
payload: {
gaugeColors: ColorNumber[]
}
}
export const updateGaugeColors = (
gaugeColors: ColorNumber[]
): UpdateGaugeColorsAction => ({
gaugeColors: ColorsModels.ColorNumber[]
): CellEditorOverlayActions.UpdateGaugeColorsAction => ({
type: 'UPDATE_GAUGE_COLORS',
payload: {
gaugeColors,
},
})
interface UpdateAxesAction {
type: 'UPDATE_AXES'
payload: {
axes: Axes
}
}
export const updateAxes = (axes: Axes): UpdateAxesAction => ({
export const updateAxes = (
axes: DashboardsModels.Axes
): CellEditorOverlayActions.UpdateAxesAction => ({
type: 'UPDATE_AXES',
payload: {
axes,
},
})
interface UpdateTableOptionsAction {
type: 'UPDATE_TABLE_OPTIONS'
payload: {
tableOptions: TableOptions
}
}
export const updateTableOptions = (
tableOptions: TableOptions
): UpdateTableOptionsAction => ({
tableOptions: DashboardsModels.TableOptions
): CellEditorOverlayActions.UpdateTableOptionsAction => ({
type: 'UPDATE_TABLE_OPTIONS',
payload: {
tableOptions,
},
})
interface UpdateLineColorsAction {
type: 'UPDATE_LINE_COLORS'
payload: {
lineColors: ColorString[]
}
}
export const updateLineColors = (
lineColors: ColorString[]
): UpdateLineColorsAction => ({
lineColors: ColorsModels.ColorString[]
): CellEditorOverlayActions.UpdateLineColorsAction => ({
type: 'UPDATE_LINE_COLORS',
payload: {
lineColors,
},
})
interface ChangeTimeFormatAction {
type: 'CHANGE_TIME_FORMAT'
payload: {
timeFormat: string
}
}
export const changeTimeFormat = (
timeFormat: string
): ChangeTimeFormatAction => ({
): CellEditorOverlayActions.ChangeTimeFormatAction => ({
type: 'CHANGE_TIME_FORMAT',
payload: {
timeFormat,
},
})
interface ChangeDecimalPlacesAction {
type: 'CHANGE_DECIMAL_PLACES'
payload: {
decimalPlaces: DecimalPlaces
}
}
export const changeDecimalPlaces = (
decimalPlaces: DecimalPlaces
): ChangeDecimalPlacesAction => ({
decimalPlaces: DashboardsModels.DecimalPlaces
): CellEditorOverlayActions.ChangeDecimalPlacesAction => ({
type: 'CHANGE_DECIMAL_PLACES',
payload: {
decimalPlaces,
},
})
interface UpdateFieldOptionsAction {
type: 'UPDATE_FIELD_OPTIONS'
payload: {
fieldOptions: FieldOption[]
}
}
export const updateFieldOptions = (
fieldOptions: FieldOption[]
): UpdateFieldOptionsAction => ({
fieldOptions: DashboardsModels.FieldOption[]
): CellEditorOverlayActions.UpdateFieldOptionsAction => ({
type: 'UPDATE_FIELD_OPTIONS',
payload: {
fieldOptions,

View File

@ -1,6 +1,4 @@
import {bindActionCreators} from 'redux'
import {InjectedRouter} from 'react-router'
import {Location} from 'history'
import {replace} from 'react-router-redux'
import _ from 'lodash'
import queryString from 'query-string'
@ -55,28 +53,27 @@ import idNormalizer, {TYPE_ID} from 'src/normalizers/id'
import {defaultTimeRange} from 'src/shared/data/timeRanges'
import {
Dashboard,
TimeRange,
Cell,
Source,
Template,
TemplateType,
URLQueryParams,
} from 'src/types'
import {CellType, DashboardName} from 'src/types/dashboard'
// Types
import {Dispatch} from 'redux'
import {InjectedRouter} from 'react-router'
import {Location} from 'history'
import {AxiosResponse} from 'axios'
import {LocationAction} from 'react-router-redux'
import * as AuthReducers from 'src/types/reducers/auth'
import * as DashboardsActions from 'src/types/actions/dashboards'
import * as DashboardsApis from 'src/types/apis/dashboards'
import * as DashboardsModels from 'src/types/dashboards'
import * as DashboardsReducers from 'src/types/reducers/dashboards'
import * as ErrorsActions from 'src/types/actions/errors'
import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources'
import * as TempVarsModels from 'src/types/tempVars'
import * as NotificationsActions from 'src/types/actions/notifications'
interface LoadDashboardsAction {
type: 'LOAD_DASHBOARDS'
payload: {
dashboards: Dashboard[]
dashboardID: number
}
}
export const loadDashboards = (
dashboards: Dashboard[],
export const loadDashboards: DashboardsActions.LoadDashboardsActionCreator = (
dashboards: DashboardsModels.Dashboard[],
dashboardID?: number
): LoadDashboardsAction => ({
): DashboardsActions.LoadDashboardsAction => ({
type: 'LOAD_DASHBOARDS',
payload: {
dashboards,
@ -84,30 +81,19 @@ export const loadDashboards = (
},
})
interface LoadDashboardAction {
type: 'LOAD_DASHBOARD'
payload: {
dashboard: Dashboard
}
}
export const loadDashboard = (dashboard: Dashboard): LoadDashboardAction => ({
export const loadDashboard: DashboardsActions.LoadDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.LoadDashboardAction => ({
type: 'LOAD_DASHBOARD',
payload: {
dashboard,
},
})
interface SetDashTimeV1Action {
type: 'SET_DASHBOARD_TIME_V1'
payload: {
dashboardID: number
timeRange: TimeRange
}
}
export const setDashTimeV1 = (
export const setDashTimeV1: DashboardsActions.SetDashTimeV1ActionCreator = (
dashboardID: number,
timeRange: TimeRange
): SetDashTimeV1Action => ({
timeRange: QueriesModels.TimeRange
): DashboardsActions.SetDashTimeV1Action => ({
type: 'SET_DASHBOARD_TIME_V1',
payload: {
dashboardID,
@ -115,120 +101,71 @@ export const setDashTimeV1 = (
},
})
interface RetainRangesDashTimeV1Action {
type: 'RETAIN_RANGES_DASHBOARD_TIME_V1'
payload: {
dashboardIDs: string[]
}
}
export const retainRangesDashTimeV1 = (
export const retainRangesDashTimeV1: DashboardsActions.RetainRangesDashTimeV1ActionCreator = (
dashboardIDs: string[]
): RetainRangesDashTimeV1Action => ({
): DashboardsActions.RetainRangesDashTimeV1Action => ({
type: 'RETAIN_RANGES_DASHBOARD_TIME_V1',
payload: {dashboardIDs},
})
interface SetTimeRangeAction {
type: 'SET_DASHBOARD_TIME_RANGE'
payload: {
timeRange: TimeRange
}
}
export const setTimeRange = (timeRange: TimeRange): SetTimeRangeAction => ({
export const setTimeRange: DashboardsActions.SetTimeRangeActionCreator = (
timeRange: QueriesModels.TimeRange
): DashboardsActions.SetTimeRangeAction => ({
type: 'SET_DASHBOARD_TIME_RANGE',
payload: {
timeRange,
},
})
interface SetZoomedTimeRangeAction {
type: 'SET_DASHBOARD_ZOOMED_TIME_RANGE'
payload: {
zoomedTimeRange: TimeRange
}
}
export const setZoomedTimeRange = (
zoomedTimeRange: TimeRange
): SetZoomedTimeRangeAction => ({
export const setZoomedTimeRange: DashboardsActions.SetZoomedTimeRangeActionCreator = (
zoomedTimeRange: QueriesModels.TimeRange
): DashboardsActions.SetZoomedTimeRangeAction => ({
type: 'SET_DASHBOARD_ZOOMED_TIME_RANGE',
payload: {
zoomedTimeRange,
},
})
interface UpdateDashboardAction {
type: 'UPDATE_DASHBOARD'
payload: {
dashboard: Dashboard
}
}
export const updateDashboard = (
dashboard: Dashboard
): UpdateDashboardAction => ({
export const updateDashboard: DashboardsActions.UpdateDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.UpdateDashboardAction => ({
type: 'UPDATE_DASHBOARD',
payload: {
dashboard,
},
})
interface CreateDashboardAction {
type: 'CREATE_DASHBOARD'
payload: {
dashboard: Dashboard
}
}
export const createDashboard = (
dashboard: Dashboard
): CreateDashboardAction => ({
export const createDashboard: DashboardsActions.CreateDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.CreateDashboardAction => ({
type: 'CREATE_DASHBOARD',
payload: {
dashboard,
},
})
interface DeleteDashboardAction {
type: 'DELETE_DASHBOARD'
payload: {
dashboard: Dashboard
dashboardID: number
}
}
export const deleteDashboard = (
dashboard: Dashboard
): DeleteDashboardAction => ({
export const deleteDashboard: DashboardsActions.DeleteDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.DeleteDashboardAction => ({
type: 'DELETE_DASHBOARD',
payload: {
dashboard,
dashboardID: dashboard.id,
},
})
interface DeleteDashboardFailedAction {
type: 'DELETE_DASHBOARD_FAILED'
payload: {
dashboard: Dashboard
}
}
export const deleteDashboardFailed = (
dashboard: Dashboard
): DeleteDashboardFailedAction => ({
export const deleteDashboardFailed: DashboardsActions.DeleteDashboardFailedActionCreator = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.DeleteDashboardFailedAction => ({
type: 'DELETE_DASHBOARD_FAILED',
payload: {
dashboard,
},
})
interface SyncDashboardCellAction {
type: 'SYNC_DASHBOARD_CELL'
payload: {
dashboard: Dashboard
cell: Cell
}
}
export const syncDashboardCell = (
dashboard: Dashboard,
cell: Cell
): SyncDashboardCellAction => ({
export const syncDashboardCell: DashboardsActions.SyncDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.SyncDashboardCellAction => ({
type: 'SYNC_DASHBOARD_CELL',
payload: {
dashboard,
@ -236,17 +173,10 @@ export const syncDashboardCell = (
},
})
interface AddDashboardCellAction {
type: 'ADD_DASHBOARD_CELL'
payload: {
dashboard: Dashboard
cell: Cell
}
}
export const addDashboardCell = (
dashboard: Dashboard,
cell: Cell
): AddDashboardCellAction => ({
export const addDashboardCell: DashboardsActions.AddDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.AddDashboardCellAction => ({
type: 'ADD_DASHBOARD_CELL',
payload: {
dashboard,
@ -254,17 +184,10 @@ export const addDashboardCell = (
},
})
interface DeleteDashboardCellAction {
type: 'DELETE_DASHBOARD_CELL'
payload: {
dashboard: Dashboard
cell: Cell
}
}
export const deleteDashboardCell = (
dashboard: Dashboard,
cell: Cell
): DeleteDashboardCellAction => ({
export const deleteDashboardCell: DashboardsActions.DeleteDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.DeleteDashboardCellAction => ({
type: 'DELETE_DASHBOARD_CELL',
payload: {
dashboard,
@ -272,17 +195,10 @@ export const deleteDashboardCell = (
},
})
interface EditCellQueryStatusAction {
type: 'EDIT_CELL_QUERY_STATUS'
payload: {
queryID: string
status: string
}
}
export const editCellQueryStatus = (
export const editCellQueryStatus: DashboardsActions.EditCellQueryStatusActionCreator = (
queryID: string,
status: string
): EditCellQueryStatusAction => ({
): DashboardsActions.EditCellQueryStatusAction => ({
type: 'EDIT_CELL_QUERY_STATUS',
payload: {
queryID,
@ -290,19 +206,11 @@ export const editCellQueryStatus = (
},
})
interface TemplateVariableSelectedAction {
type: 'TEMPLATE_VARIABLE_SELECTED'
payload: {
dashboardID: number
templateID: string
values: any[]
}
}
export const templateVariableSelected = (
export const templateVariableSelected: DashboardsActions.TemplateVariableSelectedActionCreator = (
dashboardID: number,
templateID: string,
values
): TemplateVariableSelectedAction => ({
): DashboardsActions.TemplateVariableSelectedAction => ({
type: 'TEMPLATE_VARIABLE_SELECTED',
payload: {
dashboardID,
@ -311,17 +219,10 @@ export const templateVariableSelected = (
},
})
interface TemplateVariablesSelectedByNameAction {
type: 'TEMPLATE_VARIABLES_SELECTED_BY_NAME'
payload: {
dashboardID: number
queryParams: URLQueryParams
}
}
export const templateVariablesSelectedByName = (
export const templateVariablesSelectedByName: DashboardsActions.TemplateVariablesSelectedByNameActionCreator = (
dashboardID: number,
queryParams: URLQueryParams
): TemplateVariablesSelectedByNameAction => ({
queryParams: TempVarsModels.URLQueryParams
): DashboardsActions.TemplateVariablesSelectedByNameAction => ({
type: 'TEMPLATE_VARIABLES_SELECTED_BY_NAME',
payload: {
dashboardID,
@ -329,19 +230,11 @@ export const templateVariablesSelectedByName = (
},
})
interface EditTemplateVariableValuesAction {
type: 'EDIT_TEMPLATE_VARIABLE_VALUES'
payload: {
dashboardID: number
templateID: string
values: any[]
}
}
export const editTemplateVariableValues = (
export const editTemplateVariableValues: DashboardsActions.EditTemplateVariableValuesActionCreator = (
dashboardID: number,
templateID: string,
values
): EditTemplateVariableValuesAction => ({
): DashboardsActions.EditTemplateVariableValuesAction => ({
type: 'EDIT_TEMPLATE_VARIABLE_VALUES',
payload: {
dashboardID,
@ -350,26 +243,18 @@ export const editTemplateVariableValues = (
},
})
interface SetHoverTimeAction {
type: 'SET_HOVER_TIME'
payload: {
hoverTime: string
}
}
export const setHoverTime = (hoverTime: string): SetHoverTimeAction => ({
export const setHoverTime: DashboardsActions.SetHoverTimeActionCreator = (
hoverTime: string
): DashboardsActions.SetHoverTimeAction => ({
type: 'SET_HOVER_TIME',
payload: {
hoverTime,
},
})
interface SetActiveCellAction {
type: 'SET_ACTIVE_CELL'
payload: {
activeCellID: string
}
}
export const setActiveCell = (activeCellID: string): SetActiveCellAction => ({
export const setActiveCell: DashboardsActions.SetActiveCellActionCreator = (
activeCellID: string
): DashboardsActions.SetActiveCellAction => ({
type: 'SET_ACTIVE_CELL',
payload: {
activeCellID,
@ -378,13 +263,18 @@ export const setActiveCell = (activeCellID: string): SetActiveCellAction => ({
// Async Action Creators
export const getDashboardsAsync = () => async (
dispatch
): Promise<Dashboard[] | void> => {
export const getDashboardsAsync: DashboardsActions.GetDashboardsDispatcher = (): DashboardsActions.GetDashboardsThunk => async (
dispatch: Dispatch<
| DashboardsActions.LoadDashboardsActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<DashboardsModels.Dashboard[] | void> => {
try {
const {
data: {dashboards},
} = await getDashboardsAJAX()
} = (await getDashboardsAJAX()) as AxiosResponse<
DashboardsApis.DashboardsResponse
>
dispatch(loadDashboards(dashboards))
return dashboards
} catch (error) {
@ -395,9 +285,11 @@ export const getDashboardsAsync = () => async (
// gets update-to-date names of dashboards, but does not dispatch action
// in order to avoid duplicate and out-of-sync state problems in redux
export const getDashboardsNamesAsync = (sourceID: string) => async (
dispatch
): Promise<DashboardName[] | void> => {
export const getDashboardsNamesAsync: DashboardsActions.GetDashboardsNamesDispatcher = (
sourceID: string
): DashboardsActions.GetDashboardsNamesThunk => async (
dispatch: Dispatch<ErrorsActions.ErrorThrownActionCreator>
): Promise<DashboardsModels.DashboardName[] | void> => {
try {
// TODO: change this from getDashboardsAJAX to getDashboardsNamesAJAX
// to just get dashboard names (and links) as api view call when that
@ -405,7 +297,9 @@ export const getDashboardsNamesAsync = (sourceID: string) => async (
// dashboard for each
const {
data: {dashboards},
} = await getDashboardsAJAX()
} = (await getDashboardsAJAX()) as AxiosResponse<
DashboardsApis.DashboardsResponse
>
const dashboardsNames = dashboards.map(({id, name}) => ({
id,
name,
@ -420,7 +314,7 @@ export const getDashboardsNamesAsync = (sourceID: string) => async (
export const getDashboardAsync = (dashboardID: number) => async (
dispatch
): Promise<Dashboard | null> => {
): Promise<DashboardsModels.Dashboard | null> => {
try {
const {data: dashboard} = await getDashboardAJAX(dashboardID)
dispatch(loadDashboard(dashboard))
@ -442,24 +336,33 @@ export const getChronografVersion = () => async (): Promise<string | void> => {
}
}
const removeUnselectedTemplateValues = (dashboard: Dashboard): Template[] => {
const templates = getDeep<Template[]>(dashboard, 'templates', []).map(
template => {
if (template.type === TemplateType.CSV) {
return template
}
const value = template.values.find(val => val.selected)
const values = value ? [value] : []
return {...template, values}
const removeUnselectedTemplateValues = (
dashboard: DashboardsModels.Dashboard
): TempVarsModels.Template[] => {
const templates = getDeep<TempVarsModels.Template[]>(
dashboard,
'templates',
[]
).map(template => {
if (template.type === TempVarsModels.TemplateType.CSV) {
return template
}
)
const value = template.values.find(val => val.selected)
const values = value ? [value] : []
return {...template, values}
})
return templates
}
export const putDashboard = (dashboard: Dashboard) => async (
dispatch
export const putDashboard = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.PutDashboardThunk => async (
dispatch: Dispatch<
| DashboardsActions.UpdateDashboardAction
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<void> => {
try {
// save only selected template values to server
@ -485,15 +388,19 @@ export const putDashboard = (dashboard: Dashboard) => async (
}
}
export const putDashboardByID = (dashboardID: number) => async (
dispatch,
getState
export const putDashboardByID: DashboardsActions.PutDashboardByIDDispatcher = (
dashboardID: number
): DashboardsActions.PutDashboardByIDThunk => async (
dispatch: Dispatch<ErrorsActions.ErrorThrownActionCreator>,
getState: () => DashboardsReducers.Dashboards
): Promise<void> => {
try {
const {
dashboardUI: {dashboards},
} = getState()
const dashboard: Dashboard = dashboards.find(d => d.id === +dashboardID)
const dashboard: DashboardsModels.Dashboard = dashboards.find(
d => d.id === +dashboardID
)
const templates = removeUnselectedTemplateValues(dashboard)
await updateDashboardAJAX({...dashboard, templates})
} catch (error) {
@ -502,8 +409,14 @@ export const putDashboardByID = (dashboardID: number) => async (
}
}
export const updateDashboardCell = (dashboard: Dashboard, cell: Cell) => async (
dispatch
export const updateDashboardCell: DashboardsActions.UpdateDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.UpdateDashboardCellThunk => async (
dispatch: Dispatch<
| DashboardsActions.SyncDashboardCellActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<void> => {
try {
const {data} = await updateDashboardCellAJAX(cell)
@ -514,8 +427,15 @@ export const updateDashboardCell = (dashboard: Dashboard, cell: Cell) => async (
}
}
export const deleteDashboardAsync = (dashboard: Dashboard) => async (
dispatch
export const deleteDashboardAsync: DashboardsActions.DeleteDashboardDispatcher = (
dashboard: DashboardsModels.Dashboard
): DashboardsActions.DeleteDashboardThunk => async (
dispatch: Dispatch<
| DashboardsActions.DeleteDashboardActionCreator
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
| DashboardsActions.DeleteDashboardFailedActionCreator
>
): Promise<void> => {
dispatch(deleteDashboard(dashboard))
try {
@ -532,10 +452,16 @@ export const deleteDashboardAsync = (dashboard: Dashboard) => async (
}
}
export const addDashboardCellAsync = (
dashboard: Dashboard,
cellType: CellType
) => async (dispatch): Promise<void> => {
export const addDashboardCellAsync: DashboardsActions.AddDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cellType?: DashboardsModels.CellType
): DashboardsActions.AddDashboardCellThunk => async (
dispatch: Dispatch<
| DashboardsActions.AddDashboardCellAction
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<void> => {
try {
const {data} = await addDashboardCellAJAX(
dashboard,
@ -549,10 +475,16 @@ export const addDashboardCellAsync = (
}
}
export const cloneDashboardCellAsync = (
dashboard: Dashboard,
cell: Cell
) => async (dispatch): Promise<void> => {
export const cloneDashboardCellAsync: DashboardsActions.CloneDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.CloneDashboardCellThunk => async (
dispatch: Dispatch<
| DashboardsActions.AddDashboardCellActionCreator
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<void> => {
try {
const clonedCell = getClonedDashboardCell(dashboard, cell)
const {data} = await addDashboardCellAJAX(dashboard, clonedCell)
@ -564,10 +496,16 @@ export const cloneDashboardCellAsync = (
}
}
export const deleteDashboardCellAsync = (
dashboard: Dashboard,
cell: Cell
) => async (dispatch): Promise<void> => {
export const deleteDashboardCellAsync: DashboardsActions.DeleteDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
): DashboardsActions.DeleteDashboardCellThunk => async (
dispatch: Dispatch<
| DashboardsActions.DeleteDashboardCellActionCreator
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
): Promise<void> => {
try {
await deleteDashboardCellAJAX(cell)
dispatch(deleteDashboardCell(dashboard, cell))
@ -578,9 +516,9 @@ export const deleteDashboardCellAsync = (
}
}
export const importDashboardAsync = (dashboard: Dashboard) => async (
dispatch
): Promise<void> => {
export const importDashboardAsync = (
dashboard: DashboardsModels.Dashboard
) => async (dispatch): Promise<void> => {
try {
// save only selected template values to server
const templatesWithOnlySelectedValues = removeUnselectedTemplateValues(
@ -604,7 +542,9 @@ export const importDashboardAsync = (dashboard: Dashboard) => async (
const {
data: {dashboards},
} = await getDashboardsAJAX()
} = (await getDashboardsAJAX()) as AxiosResponse<
DashboardsApis.DashboardsResponse
>
dispatch(loadDashboards(dashboards))
dispatch(notify(notifyDashboardImported(name)))
@ -622,13 +562,13 @@ export const importDashboardAsync = (dashboard: Dashboard) => async (
export const hydrateTempVarValuesAsync = (
dashboardID: number,
source: Source
source: SourcesModels.Source
) => async (dispatch, getState): Promise<void> => {
try {
const dashboard = getState().dashboardUI.dashboards.find(
d => d.id === dashboardID
)
const templates: Template[] = dashboard.templates
const templates: TempVarsModels.Template[] = dashboard.templates
const queries = templates
.filter(
template => getDeep<string>(template, 'query.influxql', '') !== ''
@ -655,9 +595,11 @@ const removeNullValues = obj => _.pickBy(obj, o => o)
export const syncURLQueryParamsFromQueryParamsObject = (
location: Location,
updatedURLQueryParams: URLQueryParams,
deletedURLQueryParams: URLQueryParams = {}
) => (dispatch): void => {
updatedURLQueryParams: TempVarsModels.URLQueryParams,
deletedURLQueryParams: TempVarsModels.URLQueryParams = {}
): DashboardsActions.SyncURLQueryFromQueryParamsObjectActionCreator => (
dispatch: Dispatch<LocationAction>
): void => {
const updatedLocationQuery = removeNullValues({
...location.query,
...updatedURLQueryParams,
@ -678,35 +620,49 @@ export const syncURLQueryParamsFromQueryParamsObject = (
dispatch(replace(updatedLocation))
}
export const syncURLQueryFromTempVars = (
export const syncURLQueryFromTempVars: DashboardsActions.SyncURLQueryFromTempVarsDispatcher = (
location: Location,
tempVars: Template[],
deletedTempVars: Template[] = [],
urlQueryParamsTimeRanges: URLQueryParams = {}
) => (dispatch): void => {
tempVars: TempVarsModels.Template[],
deletedTempVars: TempVarsModels.Template[] = [],
urlQueryParamsTimeRanges?: TempVarsModels.URLQueryParams
): DashboardsActions.SyncURLQueryFromQueryParamsObjectActionCreator => (
dispatch: Dispatch<
DashboardsActions.SyncURLQueryFromQueryParamsObjectDispatcher
>
): void => {
const updatedURLQueryParams = generateURLQueryParamsFromTempVars(tempVars)
const deletedURLQueryParams = generateURLQueryParamsFromTempVars(
deletedTempVars
)
const updatedURLQueryParamsWithTimeRange = {
let updatedURLQueryParamsWithTimeRange = {
...updatedURLQueryParams,
...urlQueryParamsTimeRanges,
}
dispatch(
syncURLQueryParamsFromQueryParamsObject(
location,
updatedURLQueryParamsWithTimeRange,
deletedURLQueryParams
)
)
if (urlQueryParamsTimeRanges) {
updatedURLQueryParamsWithTimeRange = {
...updatedURLQueryParamsWithTimeRange,
...urlQueryParamsTimeRanges,
}
}
syncURLQueryParamsFromQueryParamsObject(
location,
updatedURLQueryParamsWithTimeRange,
deletedURLQueryParams
)(dispatch)
}
const syncDashboardTempVarsFromURLQueryParams = (
dashboardID: number,
urlQueryParams: URLQueryParams
) => (dispatch, getState): void => {
urlQueryParams: TempVarsModels.URLQueryParams
): DashboardsActions.SyncDashboardTempVarsFromURLQueryParamsDispatcher => (
dispatch: Dispatch<
| NotificationsActions.PublishNotificationActionCreator
| DashboardsActions.TemplateVariableSelectedAction
>,
getState: () => DashboardsReducers.Dashboards & AuthReducers.Auth
): void => {
const {
dashboardUI,
auth: {isUsingAuth, me},
@ -738,9 +694,12 @@ const syncDashboardTempVarsFromURLQueryParams = (
const syncDashboardTimeRangeFromURLQueryParams = (
dashboardID: number,
urlQueryParams: URLQueryParams,
urlQueryParams: TempVarsModels.URLQueryParams,
location: Location
) => (dispatch, getState): void => {
): DashboardsActions.SyncDashboardTimeRangeFromURLQueryParamsDispatcher => (
dispatch: Dispatch<NotificationsActions.PublishNotificationActionCreator>,
getState: () => DashboardsReducers.Dashboards & DashboardsReducers.DashTimeV1
): void => {
const {
dashboardUI: {dashboards},
dashTimeV1,
@ -786,37 +745,45 @@ const syncDashboardTimeRangeFromURLQueryParams = (
zoomedLower: validatedZoomedTimeRange.lower,
zoomedUpper: validatedZoomedTimeRange.upper,
}
dispatch(
syncURLQueryFromTempVars(
location,
dashboard.templates,
[],
urlQueryParamsTimeRanges
)
)
syncURLQueryFromTempVars(
location,
dashboard.templates,
[],
urlQueryParamsTimeRanges
)(dispatch)
}
const syncDashboardFromURLQueryParams = (
dashboardID: number,
location: Location
) => (dispatch): void => {
): DashboardsActions.SyncDashboardFromURLQueryParamsDispatcher => (
dispatch: Dispatch<
| DashboardsActions.SyncDashboardTempVarsFromURLQueryParamsDispatcher
| DashboardsActions.SyncDashboardTimeRangeFromURLQueryParamsDispatcher
>
): void => {
const urlQueryParams = queryString.parse(window.location.search)
dispatch(syncDashboardTempVarsFromURLQueryParams(dashboardID, urlQueryParams))
dispatch(
syncDashboardTimeRangeFromURLQueryParams(
dashboardID,
urlQueryParams,
location
)
bindActionCreators(syncDashboardTempVarsFromURLQueryParams, dispatch)(
dashboardID,
urlQueryParams
)
bindActionCreators(syncDashboardTimeRangeFromURLQueryParams, dispatch)(
dashboardID,
urlQueryParams,
location
)
}
export const getDashboardWithHydratedAndSyncedTempVarsAsync = (
export const getDashboardWithHydratedAndSyncedTempVarsAsync: DashboardsActions.GetDashboardWithHydratedAndSyncedTempVarsAsyncDispatcher = (
dashboardID: number,
source: Source,
source: SourcesModels.Source,
router: InjectedRouter,
location: Location
) => async (dispatch): Promise<void> => {
): DashboardsActions.GetDashboardWithHydratedAndSyncedTempVarsAsyncThunk => async (
dispatch: Dispatch<NotificationsActions.PublishNotificationActionCreator>
): Promise<void> => {
const dashboard = await bindActionCreators(getDashboardAsync, dispatch)(
dashboardID
)
@ -831,22 +798,29 @@ export const getDashboardWithHydratedAndSyncedTempVarsAsync = (
source
)
dispatch(syncDashboardFromURLQueryParams(+dashboardID, location))
bindActionCreators(syncDashboardFromURLQueryParams, dispatch)(
+dashboardID,
location
)
}
export const setZoomedTimeRangeAsync = (
zoomedTimeRange: TimeRange,
export const setZoomedTimeRangeAsync: DashboardsActions.SetZoomedTimeRangeDispatcher = (
zoomedTimeRange: QueriesModels.TimeRange,
location: Location
) => async (dispatch): Promise<void> => {
): DashboardsActions.SetZoomedTimeRangeThunk => async (
dispatch: Dispatch<
| DashboardsActions.SetZoomedTimeRangeActionCreator
| DashboardsActions.SyncURLQueryFromQueryParamsObjectDispatcher
>
): Promise<void> => {
dispatch(setZoomedTimeRange(zoomedTimeRange))
const urlQueryParamsZoomedTimeRange = {
zoomedLower: zoomedTimeRange.lower,
zoomedUpper: zoomedTimeRange.upper,
}
dispatch(
syncURLQueryParamsFromQueryParamsObject(
location,
urlQueryParamsZoomedTimeRange
)
)
syncURLQueryParamsFromQueryParamsObject(
location,
urlQueryParamsZoomedTimeRange
)(dispatch)
}

View File

@ -1,6 +1,11 @@
import AJAX from 'utils/ajax'
import AJAX from 'src/utils/ajax'
export function getDashboards() {
import {AxiosResponse} from 'axios'
import {DashboardsResponse} from 'src/types/apis/dashboards'
export const getDashboards = (): Promise<
AxiosResponse<DashboardsResponse> | DashboardsResponse
> => {
return AJAX({
method: 'GET',
resource: 'dashboards',
@ -19,7 +24,7 @@ export const getDashboard = async dashboardID => {
}
}
export function updateDashboard(dashboard) {
export const updateDashboard = dashboard => {
return AJAX({
method: 'PUT',
url: dashboard.links.self,
@ -27,7 +32,7 @@ export function updateDashboard(dashboard) {
})
}
export function updateDashboardCell(cell) {
export const updateDashboardCell = cell => {
return AJAX({
method: 'PUT',
url: cell.links.self,

View File

@ -1,9 +1,10 @@
// Libraries
import React, {Component} from 'react'
import _ from 'lodash'
import uuid from 'uuid'
import {getDeep} from 'src/utils/wrappers'
// Components
import {ErrorHandling} from 'src/shared/decorators/errors'
import ResizeContainer from 'src/shared/components/ResizeContainer'
import QueryMaker from 'src/dashboards/components/QueryMaker'
import Visualization from 'src/dashboards/components/Visualization'
@ -11,14 +12,18 @@ import OverlayControls from 'src/dashboards/components/OverlayControls'
import DisplayOptions from 'src/dashboards/components/DisplayOptions'
import CEOBottom from 'src/dashboards/components/CEOBottom'
import * as queryTransitions from 'src/utils/queryTransitions'
// APIs
import {getQueryConfigAndStatus} from 'src/shared/apis'
// Utils
import {getDeep} from 'src/utils/wrappers'
import * as queryTransitions from 'src/utils/queryTransitions'
import defaultQueryConfig from 'src/utils/defaultQueryConfig'
import {buildQuery} from 'src/utils/influxql'
import {getQueryConfigAndStatus} from 'src/shared/apis'
import {IS_STATIC_LEGEND} from 'src/shared/constants'
import {nextSource} from 'src/dashboards/utils/sources'
// Constants
import {IS_STATIC_LEGEND} from 'src/shared/constants'
import {TYPE_QUERY_CONFIG} from 'src/dashboards/constants'
import {removeUnselectedTemplateValues} from 'src/tempVars/constants'
import {OVERLAY_TECHNOLOGY} from 'src/shared/constants/classNames'
@ -30,19 +35,13 @@ import {
} from 'src/shared/constants'
import {getCellTypeColors} from 'src/dashboards/constants/cellEditor'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {
TimeRange,
Source,
QueryConfig,
Cell,
CellQuery,
Legend,
Status,
} from 'src/types'
import {ColorString, ColorNumber} from 'src/types/colors'
import {SourceOption} from 'src/dashboards/components/OverlayControls'
// Types
import * as CellEditorOverlayActions from 'src/types/actions/cellEditorOverlay'
import * as ColorsModels from 'src/types/colors'
import * as DashboardsActions from 'src/types/actions/dashboards'
import * as DashboardsModels from 'src/types/dashboards'
import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources'
type QueryTransitions = typeof queryTransitions
type EditRawTextAsyncFunc = (
@ -58,7 +57,7 @@ export type CellEditorOverlayActions = QueryActions & {
editRawTextAsync: EditRawTextAsyncFunc
}
const staticLegend: Legend = {
const staticLegend: DashboardsModels.Legend = {
type: 'static',
orientation: 'bottom',
}
@ -69,37 +68,40 @@ interface Template {
interface QueryStatus {
queryID: string
status: Status
status: QueriesModels.Status
}
interface Props {
sources: Source[]
editQueryStatus: () => void
sources: SourcesModels.Source[]
editQueryStatus: DashboardsActions.EditCellQueryStatusActionCreator
onCancel: () => void
onSave: (cell: Cell) => void
source: Source
onSave: (cell: DashboardsModels.Cell) => void
source: SourcesModels.Source
dashboardID: number
queryStatus: QueryStatus
autoRefresh: number
templates: Template[]
timeRange: TimeRange
timeRange: QueriesModels.TimeRange
thresholdsListType: string
thresholdsListColors: ColorNumber[]
gaugeColors: ColorNumber[]
lineColors: ColorString[]
cell: Cell
thresholdsListColors: ColorsModels.ColorNumber[]
gaugeColors: ColorsModels.ColorNumber[]
lineColors: ColorsModels.ColorString[]
cell: DashboardsModels.Cell
}
interface State {
queriesWorkingDraft: QueryConfig[]
queriesWorkingDraft: QueriesModels.QueryConfig[]
activeQueryIndex: number
isDisplayOptionsTabActive: boolean
isStaticLegend: boolean
}
const createWorkingDraft = (source: Source, query: CellQuery): QueryConfig => {
const createWorkingDraft = (
source: SourcesModels.Source,
query: DashboardsModels.CellQuery
): QueriesModels.QueryConfig => {
const {queryConfig} = query
const draft: QueryConfig = {
const draft: QueriesModels.QueryConfig = {
...queryConfig,
id: uuid.v4(),
source,
@ -109,11 +111,13 @@ const createWorkingDraft = (source: Source, query: CellQuery): QueryConfig => {
}
const createWorkingDrafts = (
source: Source,
queries: CellQuery[]
): QueryConfig[] =>
source: SourcesModels.Source,
queries: DashboardsModels.CellQuery[]
): QueriesModels.QueryConfig[] =>
_.cloneDeep(
queries.map((query: CellQuery) => createWorkingDraft(source, query))
queries.map((query: DashboardsModels.CellQuery) =>
createWorkingDraft(source, query)
)
)
@ErrorHandling
@ -247,7 +251,7 @@ class CellEditorOverlay extends Component<Props, State> {
)
}
private get formattedSources(): SourceOption[] {
private get formattedSources(): SourcesModels.SourceOption[] {
const {sources} = this.props
return sources.map(s => ({
...s,
@ -302,8 +306,11 @@ class CellEditorOverlay extends Component<Props, State> {
const {queriesWorkingDraft, isStaticLegend} = this.state
const {cell, thresholdsListColors, gaugeColors, lineColors} = this.props
const queries: CellQuery[] = queriesWorkingDraft.map(q => {
const timeRange = q.range || {upper: null, lower: TEMP_VAR_DASHBOARD_TIME}
const queries: DashboardsModels.CellQuery[] = queriesWorkingDraft.map(q => {
const timeRange = q.range || {
upper: null,
lower: TEMP_VAR_DASHBOARD_TIME,
}
const source = getDeep<string | null>(q.source, 'links.self', null)
return {
queryConfig: q,
@ -319,7 +326,7 @@ class CellEditorOverlay extends Component<Props, State> {
lineColors,
})
const newCell: Cell = {
const newCell: DashboardsModels.Cell = {
...cell,
queries,
colors,
@ -341,8 +348,8 @@ class CellEditorOverlay extends Component<Props, State> {
this.setState({isStaticLegend})
}
private handleSetQuerySource = (source: Source): void => {
const queriesWorkingDraft: QueryConfig[] = this.state.queriesWorkingDraft.map(
private handleSetQuerySource = (source: SourcesModels.Source): void => {
const queriesWorkingDraft: QueriesModels.QueryConfig[] = this.state.queriesWorkingDraft.map(
q => ({
..._.cloneDeep(q),
source,
@ -418,8 +425,8 @@ class CellEditorOverlay extends Component<Props, State> {
)
const config = data.queries.find(q => q.id === id)
const nextQueries: QueryConfig[] = this.state.queriesWorkingDraft.map(
(q: QueryConfig) => {
const nextQueries: QueriesModels.QueryConfig[] = this.state.queriesWorkingDraft.map(
(q: QueriesModels.QueryConfig) => {
if (q.id === id) {
const isQuerySupportedByExplorer = !isUsingUserDefinedTempVars
@ -447,18 +454,20 @@ class CellEditorOverlay extends Component<Props, State> {
private findSelectedSource = (): string => {
const {source} = this.props
const sources = this.formattedSources
const currentSource = getDeep<Source | null>(
const currentSource = getDeep<SourcesModels.Source | null>(
this.state.queriesWorkingDraft,
'0.source',
null
)
if (!currentSource) {
const defaultSource: Source = sources.find(s => s.id === source.id)
const defaultSource: SourcesModels.Source = sources.find(
s => s.id === source.id
)
return (defaultSource && defaultSource.text) || 'No sources'
}
const selected: Source = sources.find(
const selected: SourcesModels.Source = sources.find(
s => s.links.self === currentSource.links.self
)
return (selected && selected.text) || 'No sources'
@ -502,7 +511,7 @@ class CellEditorOverlay extends Component<Props, State> {
const {queriesWorkingDraft} = this.state
return queriesWorkingDraft.every(
(query: QueryConfig) =>
(query: QueriesModels.QueryConfig) =>
(!!query.measurement && !!query.database && !!query.fields.length) ||
!!query.rawText
)
@ -522,7 +531,7 @@ class CellEditorOverlay extends Component<Props, State> {
return result
}
private get initialSource(): Source {
private get initialSource(): SourcesModels.Source {
const {
cell: {queries},
source,
@ -541,7 +550,7 @@ class CellEditorOverlay extends Component<Props, State> {
return source
}
private get source(): Source {
private get source(): SourcesModels.Source {
const {source, sources} = this.props
const query = _.get(this.state.queriesWorkingDraft, 0, {source: null})

View File

@ -1,5 +1,5 @@
import React, {Component} from 'react'
import {Cell} from 'src/types/dashboard'
import {Cell} from 'src/types/dashboards'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

View File

@ -10,30 +10,29 @@ import TimeRangeDropdown from 'src/shared/components/TimeRangeDropdown'
import GraphTips from 'src/shared/components/GraphTips'
import DashboardHeaderEdit from 'src/dashboards/components/DashboardHeaderEdit'
import DashboardSwitcher from 'src/dashboards/components/DashboardSwitcher'
import {Dashboard, TimeRange} from 'src/types'
interface DashboardName {
text: string
}
import * as AppActions from 'src/types/actions/app'
import * as DashboardsModels from 'src/types/dashboards'
import * as QueriesModels from 'src/types/queries'
interface Props {
activeDashboard: string
dashboard: Dashboard
dashboard: DashboardsModels.Dashboard
onEditDashboard: () => void
timeRange: TimeRange
timeRange: QueriesModels.TimeRange
autoRefresh: number
isEditMode?: boolean
handleChooseTimeRange: (timeRange: TimeRange) => void
handleChooseAutoRefresh: () => void
handleChooseTimeRange: (timeRange: QueriesModels.TimeRange) => void
handleChooseAutoRefresh: AppActions.SetAutoRefreshActionCreator
onManualRefresh: () => void
handleClickPresentationButton: () => void
handleClickPresentationButton: AppActions.DelayEnablePresentationModeDispatcher
onAddCell: () => void
onToggleTempVarControls: () => void
showTemplateControlBar: boolean
zoomedTimeRange: TimeRange
zoomedTimeRange: QueriesModels.TimeRange
onCancel: () => void
onSave: () => void
names: DashboardName[]
onSave: (name: string) => Promise<void>
names: DashboardsModels.DashboardName[]
isHidden: boolean
}
@ -76,7 +75,6 @@ class DashboardHeader extends Component<Props> {
handleChooseTimeRange,
timeRange: {upper, lower},
zoomedTimeRange: {upper: zoomedUpper, lower: zoomedLower},
handleClickPresentationButton,
} = this.props
return (
@ -99,13 +97,16 @@ class DashboardHeader extends Component<Props> {
/>
<button
className="btn btn-default btn-sm btn-square"
onClick={handleClickPresentationButton}
onClick={this.handleClickPresentationButton}
>
<span className="icon expand-a" />
</button>
</>
)
}
private handleClickPresentationButton = (): void => {
this.props.handleClickPresentationButton()
}
private get addCellButton(): JSX.Element {
const {dashboard, onAddCell} = this.props

View File

@ -10,7 +10,7 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {
showOverlay as showOverlayAction,
ShowOverlay,
ShowOverlayActionCreator,
} from 'src/shared/actions/overlayTechnology'
import {OverlayContext} from 'src/shared/components/OverlayTechnology'
@ -27,7 +27,7 @@ interface Props {
onExportDashboard: (dashboard: Dashboard) => () => void
onImportDashboard: (dashboard: Dashboard) => void
notify: (message: Notification) => void
showOverlay: ShowOverlay
showOverlay: ShowOverlayActionCreator
dashboardLink: string
}

View File

@ -2,7 +2,7 @@ import React, {PureComponent} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
import OptIn from 'src/shared/components/OptIn'
import {DecimalPlaces} from 'src/types/dashboard'
import {DecimalPlaces} from 'src/types/dashboards'
interface Props extends DecimalPlaces {
onDecimalPlacesChange: (decimalPlaces: DecimalPlaces) => void

View File

@ -3,11 +3,9 @@ import classnames from 'classnames'
import ConfirmOrCancel from 'src/shared/components/ConfirmOrCancel'
import SourceSelector from 'src/dashboards/components/SourceSelector'
import {QueryConfig, Source} from 'src/types'
export interface SourceOption extends Source {
text: string
}
import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources'
interface Props {
onCancel: () => void
@ -17,10 +15,10 @@ interface Props {
displayOptions: boolean
) => (event: MouseEvent<HTMLLIElement>) => void
isSavable: boolean
sources: SourceOption[]
onSetQuerySource: (source: Source) => void
sources: SourcesModels.SourceOption[]
onSetQuerySource: (source: SourcesModels.Source) => void
selected: string
queries: QueryConfig[]
queries: QueriesModels.QueryConfig[]
}
const OverlayControls: SFC<Props> = ({

View File

@ -1,13 +1,15 @@
import React, {SFC} from 'react'
import Dropdown from 'src/shared/components/Dropdown'
import {QueryConfig} from 'src/types'
import {SourceOption} from 'src/dashboards/components/OverlayControls'
import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources'
interface Props {
sources: SourceOption[]
sources: SourcesModels.SourceOption[]
selected: string
onSetQuerySource: (source: SourceOption) => void
queries: QueryConfig[]
onSetQuerySource: (source: SourcesModels.SourceOption) => void
queries: QueriesModels.QueryConfig[]
}
const SourceSelector: SFC<Props> = ({

View File

@ -24,8 +24,8 @@ import {
import {DEFAULT_TIME_FIELD} from 'src/dashboards/constants'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {DecimalPlaces} from 'src/types/dashboard'
import {QueryConfig} from 'src/types/query'
import {DecimalPlaces} from 'src/types/dashboards'
import {QueryConfig} from 'src/types/queries'
interface DropdownOption {
text: string

View File

@ -15,7 +15,7 @@ import {
DecimalPlaces,
FieldOption,
CellType,
} from 'src/types/dashboard'
} from 'src/types/dashboards'
import {ColorString, ColorNumber} from 'src/types/colors'
interface Props {

View File

@ -1,6 +1,6 @@
import {DEFAULT_TABLE_OPTIONS} from 'src/dashboards/constants'
import {stringifyColorValues} from 'src/shared/constants/colorOperations'
import {CellType, Axis} from 'src/types/dashboard'
import {CellType, Axis} from 'src/types/dashboards'
import {ColorString, ColorNumber} from 'src/types/colors'
export const initializeOptions = (cellType: CellType) => {

View File

@ -3,7 +3,7 @@ import {
DEFAULT_FIX_FIRST_COLUMN,
} from 'src/shared/constants/tableGraph'
import {Cell, QueryConfig} from 'src/types'
import {CellType, Dashboard, DecimalPlaces} from 'src/types/dashboard'
import {CellType, Dashboard, DecimalPlaces} from 'src/types/dashboards'
export const UNTITLED_GRAPH: string = 'Untitled Graph'

View File

@ -1,58 +1,129 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
// Libraries
import React, {Component, MouseEvent} from 'react'
import {connect} from 'react-redux'
import {withRouter} from 'react-router'
import {bindActionCreators} from 'redux'
import _ from 'lodash'
// Components
import {isUserAuthorized, EDITOR_ROLE} from 'src/auth/Authorized'
import {ErrorHandling} from 'src/shared/decorators/errors'
import CellEditorOverlay from 'src/dashboards/components/CellEditorOverlay'
import DashboardHeader from 'src/dashboards/components/DashboardHeader'
import Dashboard from 'src/dashboards/components/Dashboard'
import ManualRefresh from 'src/shared/components/ManualRefresh'
import TemplateControlBar from 'src/tempVars/components/TemplateControlBar'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
import {notify as notifyAction} from 'shared/actions/notifications'
// Actions
import * as dashboardActions from 'src/dashboards/actions'
import * as annotationActions from 'src/shared/actions/annotations'
import * as cellEditorOverlayActions from 'src/dashboards/actions/cellEditorOverlay'
import * as appActions from 'src/shared/actions/app'
import * as errorActions from 'src/shared/actions/errors'
import * as notifyActions from 'src/shared/actions/notifications'
// Utils
import idNormalizer, {TYPE_ID} from 'src/normalizers/id'
import {millisecondTimeRange} from 'src/dashboards/utils/time'
import * as dashboardActionCreators from 'src/dashboards/actions'
import * as annotationActions from 'shared/actions/annotations'
import {
showCellEditorOverlay,
hideCellEditorOverlay,
} from 'src/dashboards/actions/cellEditorOverlay'
import {showOverlay} from 'src/shared/actions/overlayTechnology'
import {stripTempVar} from 'src/dashboards/utils/tempVars'
import {getDeep} from 'src/utils/wrappers'
import {dismissEditingAnnotation} from 'src/shared/actions/annotations'
import {
setAutoRefresh,
templateControlBarVisibilityToggled as templateControlBarVisibilityToggledAction,
} from 'shared/actions/app'
import {presentationButtonDispatcher} from 'shared/dispatchers'
// Constants
import {
interval,
DASHBOARD_LAYOUT_ROW_HEIGHT,
TEMP_VAR_DASHBOARD_TIME,
TEMP_VAR_UPPER_DASHBOARD_TIME,
} from 'shared/constants'
} from 'src/shared/constants'
import {FORMAT_INFLUXQL, defaultTimeRange} from 'src/shared/data/timeRanges'
import {colorsStringSchema, colorsNumberSchema} from 'shared/schemas'
import {ErrorHandling} from 'src/shared/decorators/errors'
// Types
import {WithRouterProps} from 'react-router'
import {ManualRefreshProps} from 'src/shared/components/ManualRefresh'
import {Location} from 'history'
import {InjectedRouter} from 'react-router'
import * as AnnotationsActions from 'src/types/actions/annotations'
import * as AppActions from 'src/types/actions/app'
import * as CellEditorOverlayActions from 'src/types/actions/cellEditorOverlay'
import * as ColorsModels from 'src/types/colors'
import * as DashboardsActions from 'src/types/actions/dashboards'
import * as DashboardsModels from 'src/types/dashboards'
import * as ErrorsActions from 'src/types/actions/errors'
import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources'
import * as TempVarsModels from 'src/types/tempVars'
import * as NotificationsActions from 'src/types/actions/notifications'
import {getDeep} from 'src/utils/wrappers'
interface DashboardActions {
setDashTimeV1: DashboardsActions.SetDashTimeV1ActionCreator
updateDashboard: DashboardsActions.UpdateDashboardActionCreator
syncURLQueryParamsFromQueryParamsObject: DashboardsActions.SyncURLQueryFromQueryParamsObjectDispatcher
putDashboard: DashboardsActions.PutDashboardDispatcher
putDashboardByID: DashboardsActions.PutDashboardByIDDispatcher
getDashboardsNamesAsync: DashboardsActions.GetDashboardsNamesDispatcher
getDashboardWithHydratedAndSyncedTempVarsAsync: DashboardsActions.GetDashboardWithHydratedAndSyncedTempVarsAsyncDispatcher
setTimeRange: DashboardsActions.SetTimeRangeActionCreator
addDashboardCellAsync: DashboardsActions.AddDashboardCellDispatcher
editCellQueryStatus: DashboardsActions.EditCellQueryStatusActionCreator
updateDashboardCell: DashboardsActions.UpdateDashboardCellDispatcher
cloneDashboardCellAsync: DashboardsActions.CloneDashboardCellDispatcher
deleteDashboardCellAsync: DashboardsActions.DeleteDashboardCellDispatcher
templateVariableSelected: DashboardsActions.TemplateVariableSelectedActionCreator
syncURLQueryFromTempVars: DashboardsActions.SyncURLQueryFromTempVarsDispatcher
setZoomedTimeRangeAsync: DashboardsActions.SetZoomedTimeRangeDispatcher
}
interface Props extends DashboardActions, ManualRefreshProps, WithRouterProps {
source: SourcesModels.Source
sources: SourcesModels.Source[]
params: {
sourceID: string
dashboardID: string
}
location: Location
dashboardID: number
dashboard: DashboardsModels.Dashboard
dashboards: DashboardsModels.Dashboard[]
handleChooseAutoRefresh: AppActions.SetAutoRefreshActionCreator
autoRefresh: number
templateControlBarVisibilityToggled: () => AppActions.TemplateControlBarVisibilityToggledActionCreator
timeRange: QueriesModels.TimeRange
zoomedTimeRange: QueriesModels.TimeRange
showTemplateControlBar: boolean
inPresentationMode: boolean
handleClickPresentationButton: AppActions.DelayEnablePresentationModeDispatcher
cellQueryStatus: {
queryID: string
status: object
}
errorThrown: ErrorsActions.ErrorThrownActionCreator
meRole: string
isUsingAuth: boolean
router: InjectedRouter
notify: NotificationsActions.PublishNotificationActionCreator
getAnnotationsAsync: AnnotationsActions.GetAnnotationsDispatcher
handleShowCellEditorOverlay: CellEditorOverlayActions.ShowCellEditorOverlayActionCreator
handleHideCellEditorOverlay: CellEditorOverlayActions.HideCellEditorOverlayActionCreator
handleDismissEditingAnnotation: AnnotationsActions.DismissEditingAnnotationActionCreator
selectedCell: DashboardsModels.Cell
thresholdsListType: string
thresholdsListColors: ColorsModels.ColorNumber[]
gaugeColors: ColorsModels.ColorNumber[]
lineColors: ColorsModels.ColorString[]
}
interface State {
isEditMode: boolean
selectedCell: DashboardsModels.Cell | null
scrollTop: number
windowHeight: number
dashboardsNames: DashboardsModels.DashboardName[]
}
@ErrorHandling
class DashboardPage extends Component {
constructor(props) {
class DashboardPage extends Component<Props, State> {
private intervalID: number
public constructor(props: Props) {
super(props)
this.state = {
@ -64,10 +135,9 @@ class DashboardPage extends Component {
}
}
async componentDidMount() {
public async componentDidMount() {
const {
params: {dashboardID},
dashboardActions: {putDashboardByID},
dashboardID,
source,
meRole,
isUsingAuth,
@ -80,7 +150,7 @@ class DashboardPage extends Component {
getAnnotationsAsync(source.links.annotations, annotationRange)
if (autoRefresh) {
this.intervalID = setInterval(() => {
this.intervalID = window.setInterval(() => {
getAnnotationsAsync(source.links.annotations, annotationRange)
}, autoRefresh)
}
@ -93,26 +163,26 @@ class DashboardPage extends Component {
// is refactored so as not to require a write operation (a PUT in this case)
if (!isUsingAuth || isUserAuthorized(meRole, EDITOR_ROLE)) {
// putDashboardByID refreshes & persists influxql generated template variable values.
await putDashboardByID(dashboardID)
await this.props.putDashboardByID(dashboardID)
}
this.getDashboardsNames()
}
componentWillReceiveProps(nextProps) {
public componentWillReceiveProps(nextProps: Props) {
const {source, getAnnotationsAsync, timeRange} = this.props
if (this.props.autoRefresh !== nextProps.autoRefresh) {
clearInterval(this.intervalID)
const annotationRange = millisecondTimeRange(timeRange)
if (nextProps.autoRefresh) {
this.intervalID = setInterval(() => {
this.intervalID = window.setInterval(() => {
getAnnotationsAsync(source.links.annotations, annotationRange)
}, nextProps.autoRefresh)
}
}
}
componentDidUpdate(prevProps) {
public componentDidUpdate(prevProps: Props) {
const prevPath = getDeep(prevProps.location, 'pathname', null)
const thisPath = getDeep(this.props.location, 'pathname', null)
@ -121,211 +191,13 @@ class DashboardPage extends Component {
}
}
handleWindowResize = () => {
this.setState({windowHeight: window.innerHeight})
}
componentWillUnmount() {
public componentWillUnmount() {
clearInterval(this.intervalID)
this.intervalID = false
window.removeEventListener('resize', this.handleWindowResize, true)
this.props.handleDismissEditingAnnotation()
}
async getDashboard() {
const {
params: {dashboardID},
dashboardActions: {getDashboardWithHydratedAndSyncedTempVarsAsync},
source,
router,
location,
} = this.props
return await getDashboardWithHydratedAndSyncedTempVarsAsync(
dashboardID,
source,
router,
location
)
}
async getDashboardsNames() {
const {
params: {sourceID},
dashboardActions: {getDashboardsNamesAsync},
} = this.props
const dashboardsNames = await getDashboardsNamesAsync(sourceID)
this.setState({dashboardsNames})
}
inView = cell => {
const {scrollTop, windowHeight} = this.state
const bufferValue = 600
const cellTop = cell.y * DASHBOARD_LAYOUT_ROW_HEIGHT
const cellBottom = (cell.y + cell.h) * DASHBOARD_LAYOUT_ROW_HEIGHT
const bufferedWindowBottom = windowHeight + scrollTop + bufferValue
const bufferedWindowTop = scrollTop - bufferValue
const topInView = cellTop < bufferedWindowBottom
const bottomInView = cellBottom > bufferedWindowTop
return topInView && bottomInView
}
handleSaveEditedCell = newCell => {
const {
dashboardActions,
dashboard,
handleHideCellEditorOverlay,
} = this.props
dashboardActions
.updateDashboardCell(dashboard, newCell)
.then(handleHideCellEditorOverlay)
}
handleChooseTimeRange = timeRange => {
const {
dashboard,
dashboardActions,
getAnnotationsAsync,
source,
location,
} = this.props
dashboardActions.setDashTimeV1(dashboard.id, {
...timeRange,
format: FORMAT_INFLUXQL,
})
dashboardActions.syncURLQueryParamsFromQueryParamsObject(location, {
lower: timeRange.lower,
upper: timeRange.upper,
})
const annotationRange = millisecondTimeRange(timeRange)
getAnnotationsAsync(source.links.annotations, annotationRange)
}
handleUpdatePosition = cells => {
const {dashboardActions, dashboard, meRole, isUsingAuth} = this.props
const newDashboard = {...dashboard, cells}
// GridLayout invokes onLayoutChange on first load, which bubbles up to
// invoke handleUpdatePosition. If using auth, Viewer is not authorized to
// PUT, so until the need for PUT is removed, this is prevented.
if (!isUsingAuth || isUserAuthorized(meRole, EDITOR_ROLE)) {
dashboardActions.updateDashboard(newDashboard)
dashboardActions.putDashboard(newDashboard)
}
}
handleAddCell = () => {
const {dashboardActions, dashboard} = this.props
dashboardActions.addDashboardCellAsync(dashboard)
}
handleCloneCell = cell => {
const {dashboardActions, dashboard} = this.props
dashboardActions.cloneDashboardCellAsync(dashboard, cell)
}
handleEditDashboard = () => {
this.setState({isEditMode: true})
}
handleCancelEditDashboard = () => {
this.setState({isEditMode: false})
}
handleRenameDashboard = async name => {
const {dashboardActions, dashboard} = this.props
this.setState({isEditMode: false})
const newDashboard = {...dashboard, name}
dashboardActions.updateDashboard(newDashboard)
await dashboardActions.putDashboard(newDashboard)
this.getDashboardsNames()
}
handleUpdateDashboardCell = newCell => () => {
const {dashboardActions, dashboard} = this.props
dashboardActions.updateDashboardCell(dashboard, newCell)
}
handleDeleteDashboardCell = cell => {
const {dashboardActions, dashboard} = this.props
dashboardActions.deleteDashboardCellAsync(dashboard, cell)
}
handleSelectTemplate = templateID => value => {
const {
dashboardActions,
dashboard,
params: {dashboardID},
location,
} = this.props
const currentTempVar = dashboard.templates.find(
tempVar => tempVar.id === templateID
)
const strippedTempVar = stripTempVar(currentTempVar.tempVar)
const isTempVarInURLQuery = !!location.query[strippedTempVar]
if (isTempVarInURLQuery) {
const updatedQueryParam = {
[strippedTempVar]: value.value,
}
dashboardActions.syncURLQueryParamsFromQueryParamsObject(
location,
updatedQueryParam
)
}
dashboardActions.templateVariableSelected(dashboard.id, templateID, [value])
dashboardActions.putDashboardByID(dashboardID)
}
handleSaveTemplateVariables = async templates => {
const {location, dashboardActions, dashboard} = this.props
try {
await dashboardActions.putDashboard({
...dashboard,
templates,
})
const deletedTempVars = dashboard.templates.filter(
({tempVar: oldTempVar}) =>
!templates.find(({tempVar: newTempVar}) => oldTempVar === newTempVar)
)
dashboardActions.syncURLQueryFromTempVars(
location,
templates,
deletedTempVars
)
} catch (error) {
console.error(error)
}
}
handleRunQueryFailure = error => {
console.error(error)
this.props.errorThrown(error)
}
handleToggleTempVarControls = () => {
this.props.templateControlBarVisibilityToggled()
}
handleZoomedTimeRange = (zoomedLower, zoomedUpper) => {
const {dashboardActions, location} = this.props
const zoomedTimeRange = {lower: zoomedLower, upper: zoomedUpper}
dashboardActions.setZoomedTimeRangeAsync(zoomedTimeRange, location)
}
setScrollTop = event => {
this.setState({scrollTop: event.target.scrollTop})
}
render() {
public render() {
const {
isUsingAuth,
meRole,
@ -337,7 +209,7 @@ class DashboardPage extends Component {
zoomedTimeRange: {lower: zoomedLower, upper: zoomedUpper},
showTemplateControlBar,
dashboard,
dashboards,
dashboardID,
lineColors,
gaugeColors,
autoRefresh,
@ -347,13 +219,12 @@ class DashboardPage extends Component {
cellQueryStatus,
thresholdsListType,
thresholdsListColors,
dashboardActions,
inPresentationMode,
handleChooseAutoRefresh,
handleShowCellEditorOverlay,
handleHideCellEditorOverlay,
handleClickPresentationButton,
params: {sourceID, dashboardID},
} = this.props
const {dashboardsNames} = this.state
@ -416,7 +287,7 @@ class DashboardPage extends Component {
onSave={this.handleSaveEditedCell}
onCancel={handleHideCellEditorOverlay}
templates={templatesIncludingDashTime}
editQueryStatus={dashboardActions.editCellQueryStatus}
editQueryStatus={this.props.editCellQueryStatus}
thresholdsListType={thresholdsListType}
thresholdsListColors={thresholdsListColors}
gaugeColors={gaugeColors}
@ -425,9 +296,7 @@ class DashboardPage extends Component {
) : null}
<DashboardHeader
names={dashboardsNames}
sourceID={sourceID}
dashboard={dashboard}
dashboards={dashboards}
timeRange={timeRange}
isEditMode={isEditMode}
autoRefresh={autoRefresh}
@ -467,13 +336,10 @@ class DashboardPage extends Component {
autoRefresh={autoRefresh}
manualRefresh={manualRefresh}
onZoom={this.handleZoomedTimeRange}
onAddCell={this.handleAddCell}
inPresentationMode={inPresentationMode}
onPositionChange={this.handleUpdatePosition}
onSelectTemplate={this.handleSelectTemplate}
onDeleteCell={this.handleDeleteDashboardCell}
onCloneCell={this.handleCloneCell}
showTemplateControlBar={showTemplateControlBar}
templatesIncludingDashTime={templatesIncludingDashTime}
onSummonOverlayTechnologies={handleShowCellEditorOverlay}
/>
@ -481,96 +347,194 @@ class DashboardPage extends Component {
</div>
)
}
}
const {arrayOf, bool, func, number, shape, string} = PropTypes
private handleWindowResize = (): void => {
this.setState({windowHeight: window.innerHeight})
}
DashboardPage.propTypes = {
source: shape({
links: shape({
proxy: string,
self: string,
}),
}).isRequired,
sources: arrayOf(shape({})).isRequired,
params: shape({
sourceID: string.isRequired,
dashboardID: number.isRequired,
}).isRequired,
location: shape({
pathname: string.isRequired,
query: shape({}),
}).isRequired,
dashboard: shape({}),
dashboardActions: shape({
putDashboard: func.isRequired,
getDashboardsNamesAsync: func.isRequired,
getDashboardWithHydratedAndSyncedTempVarsAsync: func.isRequired,
setTimeRange: func.isRequired,
addDashboardCellAsync: func.isRequired,
}).isRequired,
dashboards: arrayOf(
shape({
id: number.isRequired,
cells: arrayOf(shape({})).isRequired,
templates: arrayOf(
shape({
type: string.isRequired,
tempVar: string.isRequired,
query: shape({
db: string,
rp: string,
influxql: string,
}),
values: arrayOf(
shape({
value: string.isRequired,
selected: bool.isRequired,
type: string.isRequired,
})
),
})
),
private getDashboard = async (): Promise<
DashboardsActions.GetDashboardWithHydratedAndSyncedTempVarsAsyncThunk
> => {
const {dashboardID, source, router, location} = this.props
return await this.props.getDashboardWithHydratedAndSyncedTempVarsAsync(
dashboardID,
source,
router,
location
)
}
private getDashboardsNames = async (): Promise<void> => {
const {
params: {sourceID},
} = this.props
// TODO: remove any once react-redux connect is properly typed
const dashboardsNames = (await this.props.getDashboardsNamesAsync(
sourceID
)) as any
this.setState({dashboardsNames})
}
private inView = (cell: DashboardsModels.Cell): boolean => {
const {scrollTop, windowHeight} = this.state
const bufferValue = 600
const cellTop = cell.y * DASHBOARD_LAYOUT_ROW_HEIGHT
const cellBottom = (cell.y + cell.h) * DASHBOARD_LAYOUT_ROW_HEIGHT
const bufferedWindowBottom = windowHeight + scrollTop + bufferValue
const bufferedWindowTop = scrollTop - bufferValue
const topInView = cellTop < bufferedWindowBottom
const bottomInView = cellBottom > bufferedWindowTop
return topInView && bottomInView
}
private handleSaveEditedCell = async (
newCell: DashboardsModels.Cell
): Promise<void> => {
const {dashboard, handleHideCellEditorOverlay} = this.props
await this.props.updateDashboardCell(dashboard, newCell)
handleHideCellEditorOverlay()
}
private handleChooseTimeRange = (
timeRange: QueriesModels.TimeRange
): void => {
const {
dashboard,
getAnnotationsAsync,
source,
location,
} = this.props
this.props.setDashTimeV1(dashboard.id, {
...timeRange,
format: FORMAT_INFLUXQL,
})
),
handleChooseAutoRefresh: func.isRequired,
autoRefresh: number.isRequired,
templateControlBarVisibilityToggled: func.isRequired,
timeRange: shape({
upper: string,
lower: string,
}),
zoomedTimeRange: shape({
upper: string,
lower: string,
}),
showTemplateControlBar: bool.isRequired,
inPresentationMode: bool.isRequired,
handleClickPresentationButton: func,
cellQueryStatus: shape({
queryID: string,
status: shape(),
}).isRequired,
errorThrown: func,
manualRefresh: number.isRequired,
onManualRefresh: func.isRequired,
meRole: string,
isUsingAuth: bool.isRequired,
router: shape().isRequired,
notify: func.isRequired,
getAnnotationsAsync: func.isRequired,
handleShowCellEditorOverlay: func.isRequired,
handleHideCellEditorOverlay: func.isRequired,
handleDismissEditingAnnotation: func.isRequired,
selectedCell: shape({}),
thresholdsListType: string.isRequired,
thresholdsListColors: colorsNumberSchema.isRequired,
gaugeColors: colorsNumberSchema.isRequired,
lineColors: colorsStringSchema.isRequired,
handleShowOverlay: func.isRequired,
this.props.syncURLQueryParamsFromQueryParamsObject(location, {
lower: timeRange.lower,
upper: timeRange.upper,
})
const annotationRange = millisecondTimeRange(timeRange)
getAnnotationsAsync(source.links.annotations, annotationRange)
}
private handleUpdatePosition = (cells: DashboardsModels.Cell[]): void => {
const {dashboard, meRole, isUsingAuth} = this.props
const newDashboard = {...dashboard, cells}
// GridLayout invokes onLayoutChange on first load, which bubbles up to
// invoke handleUpdatePosition. If using auth, Viewer is not authorized to
// PUT, so until the need for PUT is removed, this is prevented.
if (!isUsingAuth || isUserAuthorized(meRole, EDITOR_ROLE)) {
this.props.updateDashboard(newDashboard)
this.props.putDashboard(newDashboard)
}
}
private handleAddCell = (): void => {
const {dashboard} = this.props
this.props.addDashboardCellAsync(dashboard)
}
private handleCloneCell = (cell: DashboardsModels.Cell): void => {
const {dashboard} = this.props
this.props.cloneDashboardCellAsync(dashboard, cell)
}
private handleEditDashboard = (): void => {
this.setState({isEditMode: true})
}
private handleCancelEditDashboard = (): void => {
this.setState({isEditMode: false})
}
private handleRenameDashboard = async (name: string): Promise<void> => {
const {dashboard} = this.props
this.setState({isEditMode: false})
const newDashboard = {...dashboard, name}
this.props.updateDashboard(newDashboard)
await this.props.putDashboard(newDashboard)
this.getDashboardsNames()
}
private handleDeleteDashboardCell = (cell: DashboardsModels.Cell): void => {
const {dashboard} = this.props
this.props.deleteDashboardCellAsync(dashboard, cell)
}
private handleSelectTemplate = (
templateID: string
): ((value: TempVarsModels.TemplateValue) => void) => (
value: TempVarsModels.TemplateValue
): void => {
const {dashboard, dashboardID, location} = this.props
const currentTempVar = dashboard.templates.find(
tempVar => tempVar.id === templateID
)
const strippedTempVar = stripTempVar(currentTempVar.tempVar)
const isTempVarInURLQuery = !!location.query[strippedTempVar]
if (isTempVarInURLQuery) {
const updatedQueryParam = {
[strippedTempVar]: value.value,
}
this.props.syncURLQueryParamsFromQueryParamsObject(
location,
updatedQueryParam
)
}
this.props.templateVariableSelected(dashboard.id, templateID, [value])
this.props.putDashboardByID(dashboardID)
}
private handleSaveTemplateVariables = async (
templates: TempVarsModels.Template[]
): Promise<void> => {
const {location, dashboard} = this.props
try {
await this.props.putDashboard({
...dashboard,
templates,
})
const deletedTempVars = dashboard.templates.filter(
({tempVar: oldTempVar}) =>
!templates.find(({tempVar: newTempVar}) => oldTempVar === newTempVar)
)
this.props.syncURLQueryFromTempVars(location, templates, deletedTempVars)
} catch (error) {
console.error(error)
}
}
private handleToggleTempVarControls = (): void => {
this.props.templateControlBarVisibilityToggled()
}
private handleZoomedTimeRange = (
zoomedTimeRange: QueriesModels.TimeRange
): void => {
const {location} = this.props
this.props.setZoomedTimeRangeAsync(zoomedTimeRange, location)
}
private setScrollTop = (e: MouseEvent<JSX.Element>): void => {
const target = e.target as HTMLElement
this.setState({scrollTop: target.scrollTop})
}
}
const mapStateToProps = (state, {params: {dashboardID}}) => {
const mstp = (state, {params: {dashboardID}}) => {
const {
app: {
ephemeral: {inPresentationMode},
@ -606,6 +570,7 @@ const mapStateToProps = (state, {params: {dashboardID}}) => {
sources,
meRole,
dashboard,
dashboardID: Number(dashboardID),
timeRange,
zoomedTimeRange,
dashboards,
@ -622,35 +587,20 @@ const mapStateToProps = (state, {params: {dashboardID}}) => {
}
}
const mapDispatchToProps = dispatch => ({
handleChooseAutoRefresh: bindActionCreators(setAutoRefresh, dispatch),
templateControlBarVisibilityToggled: bindActionCreators(
templateControlBarVisibilityToggledAction,
dispatch
),
handleClickPresentationButton: presentationButtonDispatcher(dispatch),
dashboardActions: bindActionCreators(dashboardActionCreators, dispatch),
errorThrown: bindActionCreators(errorThrownAction, dispatch),
notify: bindActionCreators(notifyAction, dispatch),
getAnnotationsAsync: bindActionCreators(
annotationActions.getAnnotationsAsync,
dispatch
),
handleShowCellEditorOverlay: bindActionCreators(
showCellEditorOverlay,
dispatch
),
handleHideCellEditorOverlay: bindActionCreators(
hideCellEditorOverlay,
dispatch
),
handleDismissEditingAnnotation: bindActionCreators(
dismissEditingAnnotation,
dispatch
),
handleShowOverlay: bindActionCreators(showOverlay, dispatch),
})
const mdtp = {
...dashboardActions,
handleChooseAutoRefresh: appActions.setAutoRefresh,
templateControlBarVisibilityToggled:
appActions.templateControlBarVisibilityToggled,
handleClickPresentationButton: appActions.delayEnablePresentationMode,
errorThrown: errorActions.errorThrown,
notify: notifyActions.notify,
handleShowCellEditorOverlay: cellEditorOverlayActions.showCellEditorOverlay,
handleHideCellEditorOverlay: cellEditorOverlayActions.hideCellEditorOverlay,
getAnnotationsAsync: annotationActions.getAnnotationsAsync,
handleDismissEditingAnnotation: annotationActions.dismissEditingAnnotation,
}
export default connect(mapStateToProps, mapDispatchToProps)(
ManualRefresh(withRouter(DashboardPage))
export default connect(mstp, mdtp)(
ManualRefresh<Props>(withRouter<Props>(DashboardPage))
)

View File

@ -26,7 +26,7 @@ import {
import {Source, Dashboard} from 'src/types'
import {Notification} from 'src/types/notifications'
import {DashboardFile} from 'src/types/dashboard'
import {DashboardFile} from 'src/types/dashboards'
interface Props {
source: Source

View File

@ -1,6 +1,6 @@
import React, {ReactElement} from 'react'
import {CellType} from 'src/types/dashboard'
import {CellType} from 'src/types/dashboards'
type Graphic = ReactElement<HTMLDivElement>

View File

@ -14,9 +14,9 @@ import {
} from 'src/shared/constants/graphColorPalettes'
import {initializeOptions} from 'src/dashboards/constants/cellEditor'
import {Action} from 'src/dashboards/actions/cellEditorOverlay'
import {Action} from 'src/types/actions/cellEditorOverlay'
import {CellType, Cell} from 'src/types'
import {ThresholdType, TableOptions} from 'src/types/dashboard'
import {ThresholdType, TableOptions} from 'src/types/dashboards'
import {ThresholdColor, GaugeColor, LineColor} from 'src/types/colors'
interface CEOInitialState {

View File

@ -6,8 +6,8 @@ const initialState = {
const dashTimeV1 = (state = initialState, action) => {
switch (action.type) {
case 'DELETE_DASHBOARD': {
const {dashboardID} = action.payload
const ranges = state.ranges.filter(r => r.dashboardID !== dashboardID)
const {dashboard} = action.payload
const ranges = state.ranges.filter(r => r.dashboardID !== dashboard.id)
return {...state, ranges}
}

View File

@ -1,5 +1,5 @@
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants'
import {Cell, CellType, Dashboard} from 'src/types/dashboard'
import {Cell, CellType, Dashboard} from 'src/types/dashboards'
import {NewDefaultCell, UNTITLED_GRAPH} from 'src/dashboards/constants'
const getMostCommonValue = (values: number[]): number => {
@ -55,12 +55,11 @@ const getNextAvailablePosition = (dashboard, newCell) => {
export const getNewDashboardCell = (
dashboard: Dashboard,
cellType: CellType
cellType: CellType = CellType.Line
): NewDefaultCell => {
const type = cellType || CellType.Line
const typedCell = {
...NEW_DEFAULT_DASHBOARD_CELL,
type,
type: cellType,
name: UNTITLED_GRAPH,
}

View File

@ -13,7 +13,7 @@ import {
FieldOption,
TableOptions,
DecimalPlaces,
} from 'src/types/dashboard'
} from 'src/types/dashboards'
import {TimeSeriesValue} from 'src/types/series'
interface ColumnWidths {

View File

@ -1,4 +1,4 @@
import {TimeRange} from 'src/types/query'
import {TimeRange} from 'src/types/queries'
import moment from 'moment'
import {timeRanges} from 'src/shared/data/timeRanges'

View File

@ -1,7 +1,7 @@
import React, {PureComponent} from 'react'
import classnames from 'classnames'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {QueryConfig} from 'src/types/query'
import {QueryConfig} from 'src/types/queries'
interface Props {
isActive: boolean

View File

@ -5,14 +5,14 @@ import FluxOverlay from 'src/flux/components/FluxOverlay'
import {OverlayContext} from 'src/shared/components/OverlayTechnology'
import PageHeader from 'src/shared/components/PageHeader'
import {
showOverlay as showOverlayAction,
ShowOverlay,
showOverlay,
ShowOverlayActionCreator,
} from 'src/shared/actions/overlayTechnology'
import {Service} from 'src/types'
interface Props {
showOverlay: ShowOverlay
showOverlay: ShowOverlayActionCreator
service: Service
}
@ -36,9 +36,9 @@ class FluxHeader extends PureComponent<Props> {
}
private overlay = () => {
const {showOverlay, service} = this.props
const {service} = this.props
showOverlay(
this.props.showOverlay(
<OverlayContext.Consumer>
{({onDismissOverlay}) => (
<FluxOverlay
@ -54,7 +54,7 @@ class FluxHeader extends PureComponent<Props> {
}
const mdtp = {
showOverlay: showOverlayAction,
showOverlay,
}
export default connect(null, mdtp)(FluxHeader)

View File

@ -23,7 +23,7 @@ interface Props {
sources: Source[]
services: Service[]
children: ReactChildren
showOverlay: a.ShowOverlay
showOverlay: a.ShowOverlayActionCreator
fetchServicesAsync: b.FetchServicesAsync
notify: (message: Notification) => void
updateScript: UpdateScript

View File

@ -1,7 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import _ from 'lodash'
import classnames from 'classnames'
@ -19,8 +18,7 @@ import {
getAllHosts,
} from 'src/hosts/apis'
import {setAutoRefresh} from 'shared/actions/app'
import {presentationButtonDispatcher} from 'shared/dispatchers'
import {setAutoRefresh, delayEnablePresentationMode} from 'shared/actions/app'
import {ErrorHandling} from 'src/shared/decorators/errors'
@ErrorHandling
@ -235,7 +233,7 @@ HostPage.propTypes = {
handleClickPresentationButton: func,
}
const mapStateToProps = ({
const mstp = ({
app: {
ephemeral: {inPresentationMode},
persisted: {autoRefresh},
@ -245,11 +243,9 @@ const mapStateToProps = ({
autoRefresh,
})
const mapDispatchToProps = dispatch => ({
handleChooseAutoRefresh: bindActionCreators(setAutoRefresh, dispatch),
handleClickPresentationButton: presentationButtonDispatcher(dispatch),
})
const mdtp = {
handleChooseAutoRefresh: setAutoRefresh,
handleClickPresentationButton: delayEnablePresentationMode,
}
export default connect(mapStateToProps, mapDispatchToProps)(
ManualRefresh(HostPage)
)
export default connect(mstp, mdtp)(ManualRefresh(HostPage))

View File

@ -50,6 +50,8 @@ import 'src/style/chronograf.scss'
import {HEARTBEAT_INTERVAL} from 'src/shared/constants'
import * as ErrorsModels from 'src/types/errors'
const errorsQueue = []
const rootNode = getRootNode()
@ -185,7 +187,13 @@ class Root extends PureComponent<{}, State> {
if (typeof error === 'object') {
dispatch(notify(error))
} else {
dispatch(errorThrown({status: 0, auth: null}, error, 'warning'))
dispatch(
errorThrown(
{status: 0, auth: null},
error,
ErrorsModels.AlertType.Warning
)
)
}
})
}

View File

@ -5,7 +5,7 @@ import {DEFAULT_LINE_COLORS} from 'src/shared/constants/graphColorPalettes'
import {TimeRange} from 'src/types'
interface Props {
onZoom: (lower: string, upper: string) => void
onZoom: (timeRange: TimeRange) => void
timeRange: TimeRange
data: object[]
}

View File

@ -262,9 +262,9 @@ class LogsPage extends PureComponent<Props, State> {
this.props.setNamespaceAsync(namespace)
}
private handleChartZoom = (lower, upper) => {
if (lower) {
this.props.changeZoomAsync({lower, upper})
private handleChartZoom = (timeRange: TimeRange) => {
if (timeRange.lower) {
this.props.changeZoomAsync(timeRange)
this.setState({liveUpdating: true})
}
}

View File

@ -1,122 +1,66 @@
import * as api from 'src/shared/apis/annotation'
import {AnnotationInterface} from 'src/types'
import {Dispatch} from 'redux'
import * as AnnotationsActions from 'src/types/actions/annotations'
import * as AnnotationsModels from 'src/types/annotations'
export type Action =
| EditingAnnotationAction
| DismissEditingAnnotationAction
| AddingAnnotationAction
| AddingAnnotationSuccessAction
| DismissAddingAnnotationAction
| MouseEnterTempAnnotationAction
| MouseLeaveTempAnnotationAction
| LoadAnnotationsAction
| UpdateAnnotationAction
| DeleteAnnotationAction
| AddAnnotationAction
export interface EditingAnnotationAction {
type: 'EDITING_ANNOTATION'
}
export const editingAnnotation = (): EditingAnnotationAction => ({
export const editingAnnotation = (): AnnotationsActions.EditingAnnotationAction => ({
type: 'EDITING_ANNOTATION',
})
export interface DismissEditingAnnotationAction {
type: 'DISMISS_EDITING_ANNOTATION'
}
export const dismissEditingAnnotation = (): DismissEditingAnnotationAction => ({
export const dismissEditingAnnotation = (): AnnotationsActions.DismissEditingAnnotationAction => ({
type: 'DISMISS_EDITING_ANNOTATION',
})
export interface AddingAnnotationAction {
type: 'ADDING_ANNOTATION'
}
export const addingAnnotation = (): AddingAnnotationAction => ({
export const addingAnnotation = (): AnnotationsActions.AddingAnnotationAction => ({
type: 'ADDING_ANNOTATION',
})
export interface AddingAnnotationSuccessAction {
type: 'ADDING_ANNOTATION_SUCCESS'
}
export const addingAnnotationSuccess = (): AddingAnnotationSuccessAction => ({
export const addingAnnotationSuccess = (): AnnotationsActions.AddingAnnotationSuccessAction => ({
type: 'ADDING_ANNOTATION_SUCCESS',
})
export interface DismissAddingAnnotationAction {
type: 'DISMISS_ADDING_ANNOTATION'
}
export const dismissAddingAnnotation = (): DismissAddingAnnotationAction => ({
export const dismissAddingAnnotation = (): AnnotationsActions.DismissAddingAnnotationAction => ({
type: 'DISMISS_ADDING_ANNOTATION',
})
export interface MouseEnterTempAnnotationAction {
type: 'MOUSEENTER_TEMP_ANNOTATION'
}
export const mouseEnterTempAnnotation = (): MouseEnterTempAnnotationAction => ({
export const mouseEnterTempAnnotation = (): AnnotationsActions.MouseEnterTempAnnotationAction => ({
type: 'MOUSEENTER_TEMP_ANNOTATION',
})
export interface MouseLeaveTempAnnotationAction {
type: 'MOUSELEAVE_TEMP_ANNOTATION'
}
export const mouseLeaveTempAnnotation = (): MouseLeaveTempAnnotationAction => ({
export const mouseLeaveTempAnnotation = (): AnnotationsActions.MouseLeaveTempAnnotationAction => ({
type: 'MOUSELEAVE_TEMP_ANNOTATION',
})
export interface LoadAnnotationsAction {
type: 'LOAD_ANNOTATIONS'
payload: {
annotations: AnnotationInterface[]
}
}
export const loadAnnotations = (
annotations: AnnotationInterface[]
): LoadAnnotationsAction => ({
annotations: AnnotationsModels.AnnotationInterface[]
): AnnotationsActions.LoadAnnotationsAction => ({
type: 'LOAD_ANNOTATIONS',
payload: {
annotations,
},
})
export interface UpdateAnnotationAction {
type: 'UPDATE_ANNOTATION'
payload: {
annotation: AnnotationInterface
}
}
export const updateAnnotation = (
annotation: AnnotationInterface
): UpdateAnnotationAction => ({
annotation: AnnotationsModels.AnnotationInterface
): AnnotationsActions.UpdateAnnotationAction => ({
type: 'UPDATE_ANNOTATION',
payload: {
annotation,
},
})
export interface DeleteAnnotationAction {
type: 'DELETE_ANNOTATION'
payload: {
annotation: AnnotationInterface
}
}
export const deleteAnnotation = (
annotation: AnnotationInterface
): DeleteAnnotationAction => ({
annotation: AnnotationsModels.AnnotationInterface
): AnnotationsActions.DeleteAnnotationAction => ({
type: 'DELETE_ANNOTATION',
payload: {
annotation,
},
})
export interface AddAnnotationAction {
type: 'ADD_ANNOTATION'
payload: {
annotation: AnnotationInterface
}
}
export const addAnnotation = (
annotation: AnnotationInterface
): AddAnnotationAction => ({
annotation: AnnotationsModels.AnnotationInterface
): AnnotationsActions.AddAnnotationAction => ({
type: 'ADD_ANNOTATION',
payload: {
annotation,
@ -125,7 +69,7 @@ export const addAnnotation = (
export const addAnnotationAsync = (
createUrl: string,
annotation: AnnotationInterface
annotation: AnnotationsModels.AnnotationInterface
) => async dispatch => {
dispatch(addAnnotation(annotation))
const savedAnnotation = await api.createAnnotation(createUrl, annotation)
@ -133,28 +77,25 @@ export const addAnnotationAsync = (
dispatch(deleteAnnotation(annotation))
}
export interface AnnotationRange {
since: number
until: number
}
export const getAnnotationsAsync = (
export const getAnnotationsAsync: AnnotationsActions.GetAnnotationsDispatcher = (
indexUrl: string,
{since, until}: AnnotationRange
) => async dispatch => {
{since, until}: AnnotationsModels.AnnotationRange
): AnnotationsActions.GetAnnotationsThunk => async (
dispatch: Dispatch<AnnotationsActions.LoadAnnotationsAction>
): Promise<void> => {
const annotations = await api.getAnnotations(indexUrl, since, until)
dispatch(loadAnnotations(annotations))
}
export const deleteAnnotationAsync = (
annotation: AnnotationInterface
annotation: AnnotationsModels.AnnotationInterface
) => async dispatch => {
await api.deleteAnnotation(annotation)
dispatch(deleteAnnotation(annotation))
}
export const updateAnnotationAsync = (
annotation: AnnotationInterface
annotation: AnnotationsModels.AnnotationInterface
) => async dispatch => {
await api.updateAnnotation(annotation)
dispatch(updateAnnotation(annotation))

View File

@ -1,34 +0,0 @@
import {PRESENTATION_MODE_ANIMATION_DELAY} from '../constants'
// ephemeral state action creators
export const enablePresentationMode = () => ({
type: 'ENABLE_PRESENTATION_MODE',
})
export const disablePresentationMode = () => ({
type: 'DISABLE_PRESENTATION_MODE',
})
export const delayEnablePresentationMode = () => dispatch => {
setTimeout(
() => dispatch(enablePresentationMode()),
PRESENTATION_MODE_ANIMATION_DELAY
)
}
// persistent state action creators
export const setAutoRefresh = milliseconds => ({
type: 'SET_AUTOREFRESH',
payload: {
milliseconds,
},
})
export const templateControlBarVisibilityToggled = () => ({
type: 'TEMPLATE_CONTROL_BAR_VISIBILITY_TOGGLED',
})
export const noop = () => ({
type: 'NOOP',
payload: {},
})

View File

@ -0,0 +1,46 @@
import {PRESENTATION_MODE_ANIMATION_DELAY} from '../constants'
import {notify} from 'src/shared/actions/notifications'
import {notifyPresentationMode} from 'src/shared/copy/notifications'
import {Dispatch} from 'redux'
import * as AppActions from 'src/types/actions/app'
// ephemeral state action creators
export const enablePresentationMode = (): AppActions.EnablePresentationModeAction => ({
type: 'ENABLE_PRESENTATION_MODE',
})
export const disablePresentationMode = (): AppActions.DisablePresentationModeAction => ({
type: 'DISABLE_PRESENTATION_MODE',
})
export const delayEnablePresentationMode: AppActions.DelayEnablePresentationModeDispatcher = () => async (
dispatch: Dispatch<AppActions.EnablePresentationModeAction>
): Promise<NodeJS.Timer> =>
setTimeout(() => {
dispatch(enablePresentationMode())
notify(notifyPresentationMode())
}, PRESENTATION_MODE_ANIMATION_DELAY)
// persistent state action creators
export const setAutoRefresh: AppActions.SetAutoRefreshActionCreator = (
milliseconds: number
): AppActions.SetAutoRefreshAction => ({
type: 'SET_AUTOREFRESH',
payload: {
milliseconds,
},
})
export const templateControlBarVisibilityToggled = (): AppActions.TemplateControlBarVisibilityToggledAction => ({
type: 'TEMPLATE_CONTROL_BAR_VISIBILITY_TOGGLED',
})
export const noop = (): AppActions.NoopAction => ({
type: 'NOOP',
payload: {},
})

View File

@ -1,6 +0,0 @@
export const errorThrown = (error, altText, alertType) => ({
type: 'ERROR_THROWN',
error,
altText,
alertType,
})

View File

@ -0,0 +1,13 @@
import * as ErrorsActions from 'src/types/actions/errors'
import * as ErrorsModels from 'src/types/errors'
export const errorThrown = (
error: ErrorsModels.ErrorDescription,
altText?: string,
alertType?: ErrorsModels.AlertType
): ErrorsActions.ErrorThrownAction => ({
type: 'ERROR_THROWN',
error,
altText,
alertType,
})

View File

@ -1,33 +1,15 @@
import {Notification} from 'src/types'
import * as NotificationsActions from 'src/types/actions/notifications'
import * as NotificationsModels from 'src/types/notifications'
export type Action = ActionPublishNotification | ActionDismissNotification
// Publish notification
export type PublishNotification = (n: Notification) => ActionPublishNotification
export interface ActionPublishNotification {
type: 'PUBLISH_NOTIFICATION'
payload: {
notification: Notification
}
}
export const notify = (
notification: Notification
): ActionPublishNotification => ({
export const notify: NotificationsActions.PublishNotificationActionCreator = (
notification: NotificationsModels.Notification
): NotificationsActions.PublishNotificationAction => ({
type: 'PUBLISH_NOTIFICATION',
payload: {notification},
})
// Dismiss notification
export type DismissNotification = (id: string) => ActionDismissNotification
export interface ActionDismissNotification {
type: 'DISMISS_NOTIFICATION'
payload: {
id: string
}
}
export const dismissNotification = (id: string): ActionDismissNotification => ({
export const dismissNotification = (
id: string
): NotificationsActions.DismissNotificationAction => ({
type: 'DISMISS_NOTIFICATION',
payload: {id},
})

View File

@ -8,12 +8,12 @@ interface Options {
transitionTime?: number
}
export type ShowOverlay = (
export type ShowOverlayActionCreator = (
OverlayNode: OverlayNodeType,
options: Options
) => ActionOverlayNode
) => ShowOverlayAction
export interface ActionOverlayNode {
interface ShowOverlayAction {
type: 'SHOW_OVERLAY'
payload: {
OverlayNode
@ -24,7 +24,7 @@ export interface ActionOverlayNode {
export const showOverlay = (
OverlayNode: OverlayNodeType,
options: Options
) => ({
): ShowOverlayAction => ({
type: 'SHOW_OVERLAY',
payload: {OverlayNode, options},
})

View File

@ -4,7 +4,7 @@ import {showDatabases, showRetentionPolicies} from 'src/shared/apis/metaQuery'
import showDatabasesParser from 'src/shared/parsing/showDatabases'
import showRetentionPoliciesParser from 'src/shared/parsing/showRetentionPolicies'
import {Namespace} from 'src/types/query'
import {Namespace} from 'src/types/queries'
export const getDatabasesWithRetentionPolicies = async (
proxy: string

View File

@ -18,7 +18,7 @@ import {visibleAnnotations} from 'src/shared/annotations/helpers'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {AnnotationInterface, DygraphClass, Source} from 'src/types'
import {UpdateAnnotationAction} from 'src/shared/actions/annotations'
import {UpdateAnnotationAction} from 'src/types/actions/annotations'
interface Props {
dWidth: number

View File

@ -56,7 +56,7 @@ const AutoRefresh = (
inView: true,
}
private intervalID: NodeJS.Timer | null
private intervalID: number
constructor(props: Props) {
super(props)
@ -199,7 +199,7 @@ const AutoRefresh = (
this.executeQueries()
if (autoRefresh) {
this.intervalID = setInterval(this.executeQueries, autoRefresh)
this.intervalID = window.setInterval(this.executeQueries, autoRefresh)
}
}

View File

@ -2,7 +2,7 @@ import React, {SFC} from 'react'
import _ from 'lodash'
import {TEMP_VAR_DASHBOARD_TIME} from 'src/shared/constants'
import {QueryConfig} from 'src/types/query'
import {QueryConfig} from 'src/types/queries'
interface Query {
config: QueryConfig

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import _ from 'lodash'
import {QueryConfig, Source} from 'src/types'
import {Namespace} from 'src/types/query'
import {Namespace} from 'src/types/queries'
import DatabaseListItem from 'src/shared/components/DatabaseListItem'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'

View File

@ -2,7 +2,7 @@ import React, {SFC} from 'react'
import classnames from 'classnames'
import {Namespace} from 'src/types/query'
import {Namespace} from 'src/types/queries'
export interface DatabaseListItemProps {
isActive: boolean

View File

@ -62,7 +62,7 @@ interface Props {
isBarGraph?: boolean
staticLegend?: boolean
setResolution?: (w: number) => void
onZoom?: (u: number | string, l: number | string) => void
onZoom?: (timeRange: TimeRange) => void
mode?: string
}
@ -354,10 +354,13 @@ class Dygraph extends Component<Props, State> {
const {onZoom} = this.props
if (this.dygraph.isZoomed() === false) {
return onZoom(null, null)
return onZoom({lower: null, upper: null})
}
onZoom(this.formatTimeRange(lower), this.formatTimeRange(upper))
onZoom({
lower: this.formatTimeRange(lower),
upper: this.formatTimeRange(upper),
})
}
private handleDraw = () => {

View File

@ -11,8 +11,8 @@ import CustomTimeIndicator from 'src/shared/components/CustomTimeIndicator'
import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
import {EDITING} from 'src/shared/annotations/helpers'
import {cellSupportsAnnotations} from 'src/shared/constants/index'
import {Cell} from 'src/types/dashboard'
import {QueryConfig} from 'src/types/query'
import {Cell} from 'src/types/dashboards'
import {QueryConfig} from 'src/types/queries'
import {
addingAnnotation,

View File

@ -1,29 +0,0 @@
import React, {Component} from 'react'
const ManualRefresh = WrappedComponent =>
class extends Component {
constructor(props) {
super(props)
this.state = {
manualRefresh: Date.now(),
}
}
handleManualRefresh = () => {
this.setState({
manualRefresh: Date.now(),
})
}
render() {
return (
<WrappedComponent
{...this.props}
manualRefresh={this.state.manualRefresh}
onManualRefresh={this.handleManualRefresh}
/>
)
}
}
export default ManualRefresh

View File

@ -0,0 +1,41 @@
import React, {Component, ComponentClass} from 'react'
export interface ManualRefreshProps {
manualRefresh: number
onManualRefresh: () => void
}
interface ManualRefreshState {
manualRefresh: number
}
function ManualRefresh<P>(
WrappedComponent: ComponentClass<P & ManualRefreshProps>
): ComponentClass<P> {
return class extends Component<P & ManualRefreshProps, ManualRefreshState> {
public constructor(props: P & ManualRefreshProps) {
super(props)
this.state = {
manualRefresh: Date.now(),
}
}
public render() {
return (
<WrappedComponent
{...this.props}
manualRefresh={this.state.manualRefresh}
onManualRefresh={this.handleManualRefresh}
/>
)
}
private handleManualRefresh = (): void => {
this.setState({
manualRefresh: Date.now(),
})
}
}
}
export default ManualRefresh

View File

@ -1,7 +1,7 @@
import React, {PureComponent} from 'react'
import QueryMakerTab from 'src/data_explorer/components/QueryMakerTab'
import buildInfluxQLQuery from 'src/utils/influxql'
import {QueryConfig, TimeRange} from 'src/types/query'
import {QueryConfig, TimeRange} from 'src/types/queries'
interface Props {
queries: QueryConfig[]

View File

@ -7,7 +7,7 @@ import {SMALL_CELL_HEIGHT} from 'src/shared/graphs/helpers'
import {DYGRAPH_CONTAINER_V_MARGIN} from 'src/shared/constants'
import {generateThresholdsListHexs} from 'src/shared/constants/colorOperations'
import {ColorNumber} from 'src/types/colors'
import {CellType} from 'src/types/dashboard'
import {CellType} from 'src/types/dashboards'
import {Data} from 'src/types/dygraphs'
import {ErrorHandling} from 'src/shared/decorators/errors'

View File

@ -36,7 +36,7 @@ import {
FieldOption,
DecimalPlaces,
Sort,
} from 'src/types/dashboard'
} from 'src/types/dashboards'
interface Label {
label: string

View File

@ -4,9 +4,9 @@ import AlertsApp from 'src/alerts/containers/AlertsApp'
import NewsFeed from 'src/status/components/NewsFeed'
import GettingStarted from 'src/status/components/GettingStarted'
import {Cell} from 'src/types/dashboard'
import {Cell} from 'src/types/dashboards'
import {Source} from 'src/types/sources'
import {TimeRange} from 'src/types/query'
import {TimeRange} from 'src/types/queries'
import {RECENT_ALERTS_LIMIT} from 'src/status/constants'
interface Props {

View File

@ -7,7 +7,7 @@ import {
THRESHOLD_TYPE_TEXT,
} from 'src/shared/constants/thresholds'
import {CellType} from 'src/types/dashboard'
import {CellType} from 'src/types/dashboards'
const getLegibleTextColor = bgColorHex => {
const darkText = '#292933'

View File

@ -1,7 +1,7 @@
import _ from 'lodash'
import {TemplateValueType, TemplateType} from 'src/types'
import {CellType} from 'src/types/dashboard'
import {CellType} from 'src/types/dashboards'
export const NO_CELL = 'none'

View File

@ -1,10 +1,4 @@
import {TimeRange} from 'src/types/query'
interface TimeRangeOption extends TimeRange {
defaultGroupBy: string
seconds: number
inputValue: string
menuOption: string
}
import {TimeRangeOption} from 'src/types/queries'
const nowMinus30d = 'now() - 30d'

View File

@ -1,8 +0,0 @@
import {notify} from 'shared/actions/notifications'
import {delayEnablePresentationMode} from 'shared/actions/app'
import {notifyPresentationMode} from 'shared/copy/notifications'
export const presentationButtonDispatcher = dispatch => () => {
dispatch(delayEnablePresentationMode())
dispatch(notify(notifyPresentationMode()))
}

View File

@ -1,6 +1,6 @@
import {ADDING, EDITING, TEMP_ANNOTATION} from 'src/shared/annotations/helpers'
import {Action} from 'src/shared/actions/annotations'
import {Action} from 'src/types/actions/annotations'
import {AnnotationInterface} from 'src/types'
export interface AnnotationState {

View File

@ -1,5 +1,5 @@
import uuid from 'uuid'
import {Action} from 'src/shared/actions/notifications'
import {Action} from 'src/types/actions/notifications'
import {Notification} from 'src/types'
export const initialState: Notification[] = []

View File

@ -9,10 +9,7 @@ import {
AddSource,
UpdateSource,
} from 'src/shared/actions/sources'
import {
notify as notifyAction,
PublishNotification,
} from 'src/shared/actions/notifications'
import {notify as notifyAction} from 'src/shared/actions/notifications'
import {connect} from 'react-redux'
import Notifications from 'src/shared/components/Notifications'
@ -20,7 +17,6 @@ import SourceForm from 'src/sources/components/SourceForm'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import PageHeader from 'src/shared/components/PageHeader'
import {DEFAULT_SOURCE} from 'src/shared/constants'
import {Source} from 'src/types'
const INITIAL_PATH = '/sources/new'
@ -33,8 +29,11 @@ import {
} from 'src/shared/copy/notifications'
import {ErrorHandling} from 'src/shared/decorators/errors'
import * as SourcesModels from 'src/types/sources'
import * as NotificationsActions from 'src/types/actions/notifications'
interface Props extends WithRouterProps {
notify: PublishNotification
notify: NotificationsActions.PublishNotificationActionCreator
addSource: AddSource
updateSource: UpdateSource
}
@ -42,7 +41,7 @@ interface Props extends WithRouterProps {
interface State {
isCreated: boolean
isLoading: boolean
source: Partial<Source>
source: Partial<SourcesModels.Source>
editMode: boolean
isInitialSource: boolean
}

View File

@ -3,7 +3,7 @@ import {TEMP_VAR_DASHBOARD_TIME} from 'src/shared/constants'
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants/index'
import {DEFAULT_AXIS} from 'src/dashboards/constants/cellEditor'
import {Cell, CellQuery, Axes} from 'src/types'
import {CellType} from 'src/types/dashboard'
import {CellType} from 'src/types/dashboards'
const emptyQuery: CellQuery = {
query: '',

View File

@ -16,7 +16,6 @@ interface Props {
source: Source
onSelectTemplate: (id: string) => void
onSaveTemplates: (templates: Template[]) => void
onCreateTemplateVariable: () => void
}
interface State {

View File

@ -1,6 +1,6 @@
import uuid from 'uuid'
import {TimeRange} from 'src/types/query'
import {TimeRange} from 'src/types/queries'
import {TEMP_VAR_DASHBOARD_TIME} from 'src/shared/constants'
import {Template, TemplateType, TemplateValueType} from 'src/types'

View File

@ -0,0 +1,82 @@
import {Dispatch} from 'redux'
import * as AnnotationData from 'src/types/annotations'
export type Action =
| EditingAnnotationAction
| DismissEditingAnnotationAction
| AddingAnnotationAction
| AddingAnnotationSuccessAction
| DismissAddingAnnotationAction
| MouseEnterTempAnnotationAction
| MouseLeaveTempAnnotationAction
| LoadAnnotationsAction
| UpdateAnnotationAction
| DeleteAnnotationAction
| AddAnnotationAction
export interface EditingAnnotationAction {
type: 'EDITING_ANNOTATION'
}
export type DismissEditingAnnotationActionCreator = () => DismissEditingAnnotationAction
export interface DismissEditingAnnotationAction {
type: 'DISMISS_EDITING_ANNOTATION'
}
export interface AddingAnnotationAction {
type: 'ADDING_ANNOTATION'
}
export interface AddingAnnotationSuccessAction {
type: 'ADDING_ANNOTATION_SUCCESS'
}
export interface DismissAddingAnnotationAction {
type: 'DISMISS_ADDING_ANNOTATION'
}
export interface MouseEnterTempAnnotationAction {
type: 'MOUSEENTER_TEMP_ANNOTATION'
}
export interface MouseLeaveTempAnnotationAction {
type: 'MOUSELEAVE_TEMP_ANNOTATION'
}
export interface LoadAnnotationsAction {
type: 'LOAD_ANNOTATIONS'
payload: {
annotations: AnnotationData.AnnotationInterface[]
}
}
export interface UpdateAnnotationAction {
type: 'UPDATE_ANNOTATION'
payload: {
annotation: AnnotationData.AnnotationInterface
}
}
export interface DeleteAnnotationAction {
type: 'DELETE_ANNOTATION'
payload: {
annotation: AnnotationData.AnnotationInterface
}
}
export interface AddAnnotationAction {
type: 'ADD_ANNOTATION'
payload: {
annotation: AnnotationData.AnnotationInterface
}
}
export type GetAnnotationsDispatcher = (
indexUrl: string,
annotationRange: AnnotationData.AnnotationRange
) => GetAnnotationsThunk
export type GetAnnotationsThunk = (
dispatch: Dispatch<LoadAnnotationsAction>
) => Promise<void>

View File

@ -0,0 +1,39 @@
import {Dispatch} from 'redux'
export type EnablePresentationModeActionCreator = () => EnablePresentationModeAction
export interface EnablePresentationModeAction {
type: 'ENABLE_PRESENTATION_MODE'
}
export interface DisablePresentationModeAction {
type: 'DISABLE_PRESENTATION_MODE'
}
export type DelayEnablePresentationModeDispatcher = () => DelayEnablePresentationModeThunk
export type DelayEnablePresentationModeThunk = (
dispatch: Dispatch<EnablePresentationModeAction>
) => Promise<NodeJS.Timer>
export type SetAutoRefreshActionCreator = (
milliseconds: number
) => SetAutoRefreshAction
export interface SetAutoRefreshAction {
type: 'SET_AUTOREFRESH'
payload: {
milliseconds: number
}
}
export type TemplateControlBarVisibilityToggledActionCreator = () => TemplateControlBarVisibilityToggledAction
export interface TemplateControlBarVisibilityToggledAction {
type: 'TEMPLATE_CONTROL_BAR_VISIBILITY_TOGGLED'
}
export interface NoopAction {
type: 'NOOP'
payload: object
}

View File

@ -0,0 +1,111 @@
import * as ColorsModels from 'src/types/colors'
import * as DashboardsModels from 'src/types/dashboards'
export type Action =
| ShowCellEditorOverlayAction
| HideCellEditorOverlayAction
| ChangeCellTypeAction
| RenameCellAction
| UpdateThresholdsListColorsAction
| UpdateThresholdsListTypeAction
| UpdateGaugeColorsAction
| UpdateAxesAction
| UpdateTableOptionsAction
| UpdateLineColorsAction
| ChangeTimeFormatAction
| ChangeDecimalPlacesAction
| UpdateFieldOptionsAction
export type ShowCellEditorOverlayActionCreator = (
cell: DashboardsModels.Cell
) => ShowCellEditorOverlayAction
export interface ShowCellEditorOverlayAction {
type: 'SHOW_CELL_EDITOR_OVERLAY'
payload: {
cell: DashboardsModels.Cell
}
}
export type HideCellEditorOverlayActionCreator = () => HideCellEditorOverlayAction
export interface HideCellEditorOverlayAction {
type: 'HIDE_CELL_EDITOR_OVERLAY'
}
export interface ChangeCellTypeAction {
type: 'CHANGE_CELL_TYPE'
payload: {
cellType: DashboardsModels.CellType
}
}
export interface RenameCellAction {
type: 'RENAME_CELL'
payload: {
cellName: string
}
}
export interface UpdateThresholdsListColorsAction {
type: 'UPDATE_THRESHOLDS_LIST_COLORS'
payload: {
thresholdsListColors: ColorsModels.ColorNumber[]
}
}
export interface UpdateThresholdsListTypeAction {
type: 'UPDATE_THRESHOLDS_LIST_TYPE'
payload: {
thresholdsListType: DashboardsModels.ThresholdType
}
}
export interface UpdateGaugeColorsAction {
type: 'UPDATE_GAUGE_COLORS'
payload: {
gaugeColors: ColorsModels.ColorNumber[]
}
}
export interface UpdateAxesAction {
type: 'UPDATE_AXES'
payload: {
axes: DashboardsModels.Axes
}
}
export interface UpdateTableOptionsAction {
type: 'UPDATE_TABLE_OPTIONS'
payload: {
tableOptions: DashboardsModels.TableOptions
}
}
export interface UpdateLineColorsAction {
type: 'UPDATE_LINE_COLORS'
payload: {
lineColors: ColorsModels.ColorString[]
}
}
export interface ChangeTimeFormatAction {
type: 'CHANGE_TIME_FORMAT'
payload: {
timeFormat: string
}
}
export interface ChangeDecimalPlacesAction {
type: 'CHANGE_DECIMAL_PLACES'
payload: {
decimalPlaces: DashboardsModels.DecimalPlaces
}
}
export interface UpdateFieldOptionsAction {
type: 'UPDATE_FIELD_OPTIONS'
payload: {
fieldOptions: DashboardsModels.FieldOption[]
}
}

View File

@ -0,0 +1,397 @@
import {Dispatch} from 'redux'
import {InjectedRouter} from 'react-router'
import {LocationAction} from 'react-router-redux'
import {Source} from 'src/types'
import {Location} from 'history'
import * as DashboardsModels from 'src/types/dashboards'
import * as DashboardsReducers from 'src/types/reducers/dashboards'
import * as ErrorsActions from 'src/types/actions/errors'
import * as QueriesModels from 'src/types/queries'
import * as TempVarsModels from 'src/types/tempVars'
import * as NotificationsActions from 'src/types/actions/notifications'
export type LoadDashboardsActionCreator = (
dashboards: DashboardsModels.Dashboard[],
dashboardID?: number
) => LoadDashboardsAction
export interface LoadDashboardsAction {
type: 'LOAD_DASHBOARDS'
payload: {
dashboards: DashboardsModels.Dashboard[]
dashboardID: number
}
}
export type LoadDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
) => LoadDashboardAction
export interface LoadDashboardAction {
type: 'LOAD_DASHBOARD'
payload: {
dashboard: DashboardsModels.Dashboard
}
}
export interface SetDashTimeV1Action {
type: 'SET_DASHBOARD_TIME_V1'
payload: {
dashboardID: number
timeRange: QueriesModels.TimeRange
}
}
export type SetDashTimeV1ActionCreator = (
dashboardID: number,
timeRange: QueriesModels.TimeRange
) => SetDashTimeV1Action
export interface RetainRangesDashTimeV1Action {
type: 'RETAIN_RANGES_DASHBOARD_TIME_V1'
payload: {
dashboardIDs: string[]
}
}
export type RetainRangesDashTimeV1ActionCreator = (
dashboardIDs: string[]
) => RetainRangesDashTimeV1Action
export type SetTimeRangeActionCreator = (
timeRange: QueriesModels.TimeRange
) => SetTimeRangeAction
export interface SetTimeRangeAction {
type: 'SET_DASHBOARD_TIME_RANGE'
payload: {
timeRange: QueriesModels.TimeRange
}
}
export type SetZoomedTimeRangeDispatcher = (
zoomedTimeRange: QueriesModels.TimeRange,
location: Location
) => SetZoomedTimeRangeThunk
export type SetZoomedTimeRangeThunk = (
dispatch: Dispatch<
| SetZoomedTimeRangeActionCreator
| SyncURLQueryFromQueryParamsObjectDispatcher
>
) => Promise<void>
export type SetZoomedTimeRangeActionCreator = (
zoomedTimeRange: QueriesModels.TimeRange
) => SetZoomedTimeRangeAction
export interface SetZoomedTimeRangeAction {
type: 'SET_DASHBOARD_ZOOMED_TIME_RANGE'
payload: {
zoomedTimeRange: QueriesModels.TimeRange
}
}
export interface UpdateDashboardAction {
type: 'UPDATE_DASHBOARD'
payload: {
dashboard: DashboardsModels.Dashboard
}
}
export type UpdateDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
) => UpdateDashboardAction
export type CreateDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
) => CreateDashboardAction
export interface CreateDashboardAction {
type: 'CREATE_DASHBOARD'
payload: {
dashboard: DashboardsModels.Dashboard
}
}
export type DeleteDashboardActionCreator = (
dashboard: DashboardsModels.Dashboard
) => DeleteDashboardAction
export interface DeleteDashboardAction {
type: 'DELETE_DASHBOARD'
payload: {
dashboard: DashboardsModels.Dashboard
}
}
export type DeleteDashboardFailedActionCreator = (
dashboard: DashboardsModels.Dashboard
) => DeleteDashboardFailedAction
export interface DeleteDashboardFailedAction {
type: 'DELETE_DASHBOARD_FAILED'
payload: {
dashboard: DashboardsModels.Dashboard
}
}
export type SyncDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => SyncDashboardCellAction
export interface SyncDashboardCellAction {
type: 'SYNC_DASHBOARD_CELL'
payload: {
dashboard: DashboardsModels.Dashboard
cell: DashboardsModels.Cell
}
}
export type AddDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cellType?: DashboardsModels.CellType
) => AddDashboardCellThunk
export type AddDashboardCellThunk = (
dispatch: Dispatch<
| AddDashboardCellAction
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
) => Promise<void>
export type AddDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => AddDashboardCellAction
export interface AddDashboardCellAction {
type: 'ADD_DASHBOARD_CELL'
payload: {
dashboard: DashboardsModels.Dashboard
cell: DashboardsModels.Cell
}
}
export type CloneDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => CloneDashboardCellThunk
export type CloneDashboardCellThunk = (
dispatch: Dispatch<
| AddDashboardCellAction
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
) => Promise<void>
export type DeleteDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => DeleteDashboardCellThunk
export type DeleteDashboardCellThunk = (
dispatch: Dispatch<
| DeleteDashboardCellActionCreator
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
>
) => Promise<void>
export type DeleteDashboardCellActionCreator = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => DeleteDashboardCellAction
export interface DeleteDashboardCellAction {
type: 'DELETE_DASHBOARD_CELL'
payload: {
dashboard: DashboardsModels.Dashboard
cell: DashboardsModels.Cell
}
}
export type EditCellQueryStatusActionCreator = (
queryID: string,
status: string
) => EditCellQueryStatusAction
export interface EditCellQueryStatusAction {
type: 'EDIT_CELL_QUERY_STATUS'
payload: {
queryID: string
status: string
}
}
export type TemplateVariableSelectedActionCreator = (
dashboardID: number,
templateID: string,
values: any[]
) => TemplateVariableSelectedAction
export interface TemplateVariableSelectedAction {
type: 'TEMPLATE_VARIABLE_SELECTED'
payload: {
dashboardID: number
templateID: string
values: any[]
}
}
export type TemplateVariablesSelectedByNameActionCreator = (
dashboardID: number,
queryParams: TempVarsModels.URLQueryParams
) => TemplateVariablesSelectedByNameAction
export interface TemplateVariablesSelectedByNameAction {
type: 'TEMPLATE_VARIABLES_SELECTED_BY_NAME'
payload: {
dashboardID: number
queryParams: TempVarsModels.URLQueryParams
}
}
export type EditTemplateVariableValuesActionCreator = (
dashboardID: number,
templateID: string,
values: any[]
) => EditTemplateVariableValuesAction
export interface EditTemplateVariableValuesAction {
type: 'EDIT_TEMPLATE_VARIABLE_VALUES'
payload: {
dashboardID: number
templateID: string
values: any[]
}
}
export type SetHoverTimeActionCreator = (
hoverTime: string
) => SetHoverTimeAction
export interface SetHoverTimeAction {
type: 'SET_HOVER_TIME'
payload: {
hoverTime: string
}
}
export type SetActiveCellActionCreator = (
activeCellID: string
) => SetActiveCellAction
export interface SetActiveCellAction {
type: 'SET_ACTIVE_CELL'
payload: {
activeCellID: string
}
}
export type GetDashboardsDispatcher = () => GetDashboardsThunk
export type GetDashboardsThunk = (
dispatch: Dispatch<ErrorsActions.ErrorThrownActionCreator>
) => Promise<DashboardsModels.Dashboard[] | void>
export type GetDashboardsNamesDispatcher = (
sourceID: string
) => GetDashboardsNamesThunk
export type GetDashboardsNamesThunk = (
dispatch: Dispatch<ErrorsActions.ErrorThrownActionCreator>
) => Promise<DashboardsModels.DashboardName[] | void>
export type PutDashboardDispatcher = (
dashboard: DashboardsModels.Dashboard
) => PutDashboardThunk
export type PutDashboardThunk = (
dispatch: Dispatch<
UpdateDashboardAction | ErrorsActions.ErrorThrownActionCreator
>
) => Promise<void>
export type PutDashboardByIDDispatcher = (
dashboardID: number
) => PutDashboardByIDThunk
export type PutDashboardByIDThunk = (
dispatch: Dispatch<ErrorsActions.ErrorThrownActionCreator>,
getState: () => DashboardsReducers.Dashboards
) => Promise<void>
export type DeleteDashboardDispatcher = (
dashboard: DashboardsModels.Dashboard
) => DeleteDashboardThunk
export type DeleteDashboardThunk = (
dispatch: Dispatch<
| DeleteDashboardActionCreator
| NotificationsActions.PublishNotificationActionCreator
| ErrorsActions.ErrorThrownActionCreator
| DeleteDashboardFailedActionCreator
>
) => Promise<void>
export type UpdateDashboardCellDispatcher = (
dashboard: DashboardsModels.Dashboard,
cell: DashboardsModels.Cell
) => UpdateDashboardCellThunk
export type UpdateDashboardCellThunk = (
dispatch: Dispatch<SyncDashboardCellActionCreator | ErrorsActions.ErrorThrownActionCreator>
) => Promise<void>
export type SyncURLQueryFromQueryParamsObjectDispatcher = (
location: Location,
updatedURLQueryParams: TempVarsModels.URLQueryParams,
deletedURLQueryParams?: TempVarsModels.URLQueryParams
) => SyncURLQueryFromQueryParamsObjectActionCreator
export type SyncURLQueryFromTempVarsDispatcher = (
location: Location,
tempVars: TempVarsModels.Template[],
deletedTempVars: TempVarsModels.Template[],
urlQueryParamsTimeRanges?: TempVarsModels.URLQueryParams
) => SyncURLQueryFromQueryParamsObjectActionCreator
export type SyncURLQueryFromQueryParamsObjectActionCreator = (
dispatch: Dispatch<LocationAction>
) => void
export type SyncDashboardTempVarsFromURLQueryParamsDispatcher = (
dispatch: Dispatch<
| NotificationsActions.PublishNotificationActionCreator
| TemplateVariableSelectedAction
>,
getState: () => DashboardsReducers.Dashboards & DashboardsReducers.Auth
) => void
export type SyncDashboardTimeRangeFromURLQueryParamsDispatcher = (
dispatch: Dispatch<NotificationsActions.PublishNotificationActionCreator>,
getState: () => DashboardsReducers.Dashboards & DashboardsReducers.DashTimeV1
) => void
export type SyncDashboardFromURLQueryParamsDispatcher = (
dispatch: Dispatch<
| SyncDashboardTempVarsFromURLQueryParamsDispatcher
| SyncDashboardTimeRangeFromURLQueryParamsDispatcher
>
) => void
export type GetDashboardWithHydratedAndSyncedTempVarsAsyncDispatcher = (
dashboardID: number,
source: Source,
router: InjectedRouter,
location: Location
) => GetDashboardWithHydratedAndSyncedTempVarsAsyncThunk
export type GetDashboardWithHydratedAndSyncedTempVarsAsyncThunk = (
dispatch: Dispatch<NotificationsActions.PublishNotificationActionCreator>
) => Promise<void>

View File

@ -0,0 +1,14 @@
import * as ErrorData from 'src/types/errors'
export type ErrorThrownActionCreator = (
error: ErrorData.ErrorDescription,
altText?: string,
alertType?: ErrorData.AlertType
) => ErrorThrownAction
export interface ErrorThrownAction {
type: 'ERROR_THROWN'
error: ErrorData.ErrorDescription
altText?: string
alertType?: ErrorData.AlertType
}

View File

@ -0,0 +1,23 @@
import {Notification} from 'src/types'
export type Action = PublishNotificationAction | DismissNotificationAction
export type PublishNotificationActionCreator = (
n: Notification
) => PublishNotificationAction
export interface PublishNotificationAction {
type: 'PUBLISH_NOTIFICATION'
payload: {
notification: Notification
}
}
export type DismissNotification = (id: string) => DismissNotificationAction
export interface DismissNotificationAction {
type: 'DISMISS_NOTIFICATION'
payload: {
id: string
}
}

View File

@ -6,3 +6,8 @@ export interface AnnotationInterface {
type: string
links: {self: string}
}
export interface AnnotationRange {
since: number
until: number
}

View File

@ -0,0 +1,5 @@
import {Dashboard} from 'src/types/dashboards'
export interface DashboardsResponse {
dashboards: Dashboard[]
}

13
ui/src/types/errors.ts Normal file
View File

@ -0,0 +1,13 @@
export interface ErrorDescription {
status: number
auth: {
links: {
me: string
}
}
}
export enum AlertType {
Info = 'info',
Warning = 'warning',
}

View File

@ -1,7 +1,7 @@
import {LayoutCell, LayoutQuery} from './layouts'
import {Service, NewService} from './services'
import {AuthLinks, Organization, Role, User, Me} from './auth'
import {Cell, CellQuery, Legend, Axes, Dashboard, CellType} from './dashboard'
import {Cell, CellQuery, Legend, Axes, Dashboard, CellType} from './dashboards'
import {
Template,
TemplateQuery,
@ -27,7 +27,7 @@ import {
Tag,
Tags,
TagValues,
} from './query'
} from './queries'
import {AlertRule, Kapacitor, Task, RuleValues} from './kapacitor'
import {NewSource, Source, SourceLinks} from './sources'
import {DropdownAction, DropdownItem, Constructable} from './shared'

View File

@ -87,6 +87,7 @@ export interface TimeRange {
lower: string
upper?: string | null
seconds?: number
format?: string
}
export interface DurationRange {
@ -99,3 +100,12 @@ export interface TimeShift {
unit: string
quantity: string
}
export interface TimeRangeOption extends TimeRange {
defaultGroupBy: string
seconds: number
inputValue: string
menuOption: string
}
export type DashTimeV1Range = TimeRangeOption & {dashboardID: number}

View File

@ -0,0 +1,8 @@
import * as AuthModels from 'src/types/auth'
export interface Auth {
auth: {
isUsingAuth: boolean
me: AuthModels.Me
}
}

View File

@ -0,0 +1,15 @@
import {Dashboard} from 'src/types'
import {Me} from 'src/types/auth'
import {DashTimeV1Range} from 'src/types/queries'
export interface Dashboards {
dashboardUI: {dashboards: Dashboard[]}
}
export interface Auth {
auth: {isUsingAuth: boolean; me: Me}
}
export interface DashTimeV1 {
dashTimeV1: {ranges: DashTimeV1Range[]}
}

View File

@ -37,3 +37,7 @@ export interface SourceLinks {
health: string
services: string
}
export interface SourceOption extends Source {
text: string
}

View File

@ -72,7 +72,7 @@ function generateResponseWithLinks<T extends object>(
}
interface RequestParams {
url: string | string[]
url?: string | string[]
resource?: string | null
id?: string | null
method?: string

View File

@ -37,7 +37,7 @@ const setup = (override = {}) => {
thresholdsListColors,
gaugeColors,
lineColors,
editQueryStatus: () => {},
editQueryStatus: () => null,
onCancel: () => {},
onSave: () => {},
notify: () => {},

View File

@ -15,9 +15,9 @@ import {
TableOptions,
FieldOption,
DecimalPlaces,
} from 'src/types/dashboard'
CellType,
} from 'src/types/dashboards'
import {LineColor, ColorNumber} from 'src/types/colors'
import {CellType} from 'src/types/dashboard'
export const sourceLinks: SourceLinks = {
services: '/chronograf/v1/sources/4',

View File

@ -2,7 +2,6 @@ import appReducer from 'shared/reducers/app'
import {
enablePresentationMode,
disablePresentationMode,
// delayEnablePresentationMode,
setAutoRefresh,
templateControlBarVisibilityToggled,
} from 'shared/actions/app'