remove js component cell editor overlay
parent
ac97228d8c
commit
f61d4c4d2c
|
@ -1,387 +0,0 @@
|
|||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import _ from 'lodash'
|
||||
import uuid from 'uuid'
|
||||
|
||||
import ResizeContainer from 'src/shared/components/ResizeContainer'
|
||||
import QueryMaker from 'src/dashboards/components/QueryMaker'
|
||||
import Visualization from 'src/dashboards/components/Visualization'
|
||||
import OverlayControls from 'src/dashboards/components/OverlayControls'
|
||||
import DisplayOptions from 'src/dashboards/components/DisplayOptions'
|
||||
|
||||
import * as queryModifiers from 'src/utils/queryTransitions'
|
||||
|
||||
import defaultQueryConfig from 'src/utils/defaultQueryConfig'
|
||||
import {buildQuery} from 'utils/influxql'
|
||||
import {getQueryConfig} from 'shared/apis'
|
||||
import {IS_STATIC_LEGEND} from 'src/shared/constants'
|
||||
|
||||
import {
|
||||
removeUnselectedTemplateValues,
|
||||
TYPE_QUERY_CONFIG,
|
||||
} from 'src/dashboards/constants'
|
||||
import {OVERLAY_TECHNOLOGY} from 'src/shared/constants/classNames'
|
||||
import {MINIMUM_HEIGHTS, INITIAL_HEIGHTS} from 'src/data_explorer/constants'
|
||||
import {AUTO_GROUP_BY} from 'src/shared/constants'
|
||||
import {getCellTypeColors} from 'src/dashboards/constants/cellEditor'
|
||||
import {colorsStringSchema, colorsNumberSchema} from 'shared/schemas'
|
||||
|
||||
class CellEditorOverlay extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
const {cell: {queries = [], legend}, sources} = props
|
||||
|
||||
let source = _.get(queries, ['0', 'source'], null)
|
||||
source = sources.find(s => s.links.self === source) || props.source
|
||||
|
||||
const queriesWorkingDraft = _.cloneDeep(
|
||||
queries.map(({queryConfig}) => ({
|
||||
...queryConfig,
|
||||
id: uuid.v4(),
|
||||
source,
|
||||
}))
|
||||
)
|
||||
|
||||
this.state = {
|
||||
queriesWorkingDraft,
|
||||
activeQueryIndex: 0,
|
||||
isDisplayOptionsTabActive: false,
|
||||
staticLegend: IS_STATIC_LEGEND(legend),
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {status, queryID} = this.props.queryStatus
|
||||
const nextStatus = nextProps.queryStatus
|
||||
if (nextStatus.status && nextStatus.queryID) {
|
||||
if (nextStatus.queryID !== queryID || nextStatus.status !== status) {
|
||||
const nextQueries = this.state.queriesWorkingDraft.map(
|
||||
q => (q.id === queryID ? {...q, status: nextStatus.status} : q)
|
||||
)
|
||||
this.setState({queriesWorkingDraft: nextQueries})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.overlayRef.focus()
|
||||
}
|
||||
|
||||
queryStateReducer = queryModifier => (queryID, ...payload) => {
|
||||
const {queriesWorkingDraft} = this.state
|
||||
const query = queriesWorkingDraft.find(q => q.id === queryID)
|
||||
|
||||
const nextQuery = queryModifier(query, ...payload)
|
||||
|
||||
const nextQueries = queriesWorkingDraft.map(
|
||||
q =>
|
||||
q.id === query.id
|
||||
? {...nextQuery, source: this.nextSource(q, nextQuery)}
|
||||
: q
|
||||
)
|
||||
|
||||
this.setState({queriesWorkingDraft: nextQueries})
|
||||
}
|
||||
|
||||
handleAddQuery = () => {
|
||||
const {queriesWorkingDraft} = this.state
|
||||
const newIndex = queriesWorkingDraft.length
|
||||
|
||||
this.setState({
|
||||
queriesWorkingDraft: [
|
||||
...queriesWorkingDraft,
|
||||
defaultQueryConfig({id: uuid.v4()}),
|
||||
],
|
||||
})
|
||||
this.handleSetActiveQueryIndex(newIndex)
|
||||
}
|
||||
|
||||
handleDeleteQuery = index => {
|
||||
const nextQueries = this.state.queriesWorkingDraft.filter(
|
||||
(__, i) => i !== index
|
||||
)
|
||||
this.setState({queriesWorkingDraft: nextQueries})
|
||||
}
|
||||
|
||||
handleSaveCell = () => {
|
||||
const {queriesWorkingDraft, staticLegend} = this.state
|
||||
const {cell, thresholdsListColors, gaugeColors, lineColors} = this.props
|
||||
|
||||
const queries = queriesWorkingDraft.map(q => {
|
||||
const timeRange = q.range || {upper: null, lower: ':dashboardTime:'}
|
||||
const query = q.rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, q)
|
||||
|
||||
return {
|
||||
queryConfig: q,
|
||||
query,
|
||||
source: _.get(q, ['source', 'links', 'self'], null),
|
||||
}
|
||||
})
|
||||
|
||||
const colors = getCellTypeColors({
|
||||
cellType: cell.type,
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
})
|
||||
|
||||
this.props.onSave({
|
||||
...cell,
|
||||
queries,
|
||||
colors,
|
||||
legend: staticLegend
|
||||
? {
|
||||
type: 'static',
|
||||
orientation: 'bottom',
|
||||
}
|
||||
: {},
|
||||
})
|
||||
}
|
||||
|
||||
handleClickDisplayOptionsTab = isDisplayOptionsTabActive => () => {
|
||||
this.setState({isDisplayOptionsTabActive})
|
||||
}
|
||||
|
||||
handleSetActiveQueryIndex = activeQueryIndex => {
|
||||
this.setState({activeQueryIndex})
|
||||
}
|
||||
|
||||
handleToggleStaticLegend = staticLegend => () => {
|
||||
this.setState({staticLegend})
|
||||
}
|
||||
|
||||
handleSetQuerySource = source => {
|
||||
const queriesWorkingDraft = this.state.queriesWorkingDraft.map(q => ({
|
||||
..._.cloneDeep(q),
|
||||
source,
|
||||
}))
|
||||
|
||||
this.setState({queriesWorkingDraft})
|
||||
}
|
||||
|
||||
getActiveQuery = () => {
|
||||
const {queriesWorkingDraft, activeQueryIndex} = this.state
|
||||
const activeQuery = queriesWorkingDraft[activeQueryIndex]
|
||||
const defaultQuery = queriesWorkingDraft[0]
|
||||
|
||||
return activeQuery || defaultQuery
|
||||
}
|
||||
|
||||
handleEditRawText = async (url, id, text) => {
|
||||
const templates = removeUnselectedTemplateValues(this.props.templates)
|
||||
|
||||
// use this as the handler passed into fetchTimeSeries to update a query status
|
||||
try {
|
||||
const {data} = await getQueryConfig(url, [{query: text, id}], templates)
|
||||
const config = data.queries.find(q => q.id === id)
|
||||
const nextQueries = this.state.queriesWorkingDraft.map(
|
||||
q => (q.id === id ? {...config.queryConfig, source: q.source} : q)
|
||||
)
|
||||
this.setState({queriesWorkingDraft: nextQueries})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
formatSources = this.props.sources.map(s => ({
|
||||
...s,
|
||||
text: `${s.name} @ ${s.url}`,
|
||||
}))
|
||||
|
||||
findSelectedSource = () => {
|
||||
const {source} = this.props
|
||||
const sources = this.formatSources
|
||||
const query = _.get(this.state.queriesWorkingDraft, 0, false)
|
||||
|
||||
if (!query || !query.source) {
|
||||
const defaultSource = sources.find(s => s.id === source.id)
|
||||
return (defaultSource && defaultSource.text) || 'No sources'
|
||||
}
|
||||
|
||||
const selected = sources.find(s => s.id === query.source.id)
|
||||
return (selected && selected.text) || 'No sources'
|
||||
}
|
||||
|
||||
getSource = () => {
|
||||
const {source, sources} = this.props
|
||||
const query = _.get(this.state.queriesWorkingDraft, 0, false)
|
||||
|
||||
if (!query || !query.source) {
|
||||
return source
|
||||
}
|
||||
|
||||
const querySource = sources.find(s => s.id === query.source.id)
|
||||
return querySource || source
|
||||
}
|
||||
|
||||
nextSource = (prevQuery, nextQuery) => {
|
||||
if (nextQuery.source) {
|
||||
return nextQuery.source
|
||||
}
|
||||
|
||||
return prevQuery.source
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
if (e.key === 'Enter' && e.metaKey && e.target === this.overlayRef) {
|
||||
this.handleSaveCell()
|
||||
}
|
||||
if (e.key === 'Enter' && e.metaKey && e.target !== this.overlayRef) {
|
||||
e.target.blur()
|
||||
setTimeout(this.handleSaveCell, 50)
|
||||
}
|
||||
if (e.key === 'Escape' && e.target === this.overlayRef) {
|
||||
this.props.onCancel()
|
||||
}
|
||||
if (e.key === 'Escape' && e.target !== this.overlayRef) {
|
||||
const targetIsDropdown = e.target.classList[0] === 'dropdown'
|
||||
const targetIsButton = e.target.tagName === 'BUTTON'
|
||||
|
||||
if (targetIsDropdown || targetIsButton) {
|
||||
return this.props.onCancel()
|
||||
}
|
||||
|
||||
e.target.blur()
|
||||
this.overlayRef.focus()
|
||||
}
|
||||
}
|
||||
|
||||
handleResetFocus = () => {
|
||||
this.overlayRef.focus()
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
onCancel,
|
||||
templates,
|
||||
timeRange,
|
||||
autoRefresh,
|
||||
editQueryStatus,
|
||||
} = this.props
|
||||
|
||||
const {
|
||||
activeQueryIndex,
|
||||
isDisplayOptionsTabActive,
|
||||
queriesWorkingDraft,
|
||||
staticLegend,
|
||||
} = this.state
|
||||
|
||||
const queryActions = {
|
||||
editRawTextAsync: this.handleEditRawText,
|
||||
..._.mapValues(queryModifiers, qm => this.queryStateReducer(qm)),
|
||||
}
|
||||
|
||||
const isQuerySavable = query =>
|
||||
(!!query.measurement && !!query.database && !!query.fields.length) ||
|
||||
!!query.rawText
|
||||
|
||||
return (
|
||||
<div
|
||||
className={OVERLAY_TECHNOLOGY}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
tabIndex="0"
|
||||
ref={r => (this.overlayRef = r)}
|
||||
>
|
||||
<ResizeContainer
|
||||
containerClass="resizer--full-size"
|
||||
minTopHeight={MINIMUM_HEIGHTS.visualization}
|
||||
minBottomHeight={MINIMUM_HEIGHTS.queryMaker}
|
||||
initialTopHeight={INITIAL_HEIGHTS.visualization}
|
||||
initialBottomHeight={INITIAL_HEIGHTS.queryMaker}
|
||||
>
|
||||
<Visualization
|
||||
timeRange={timeRange}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
queryConfigs={queriesWorkingDraft}
|
||||
editQueryStatus={editQueryStatus}
|
||||
staticLegend={staticLegend}
|
||||
/>
|
||||
<CEOBottom>
|
||||
<OverlayControls
|
||||
onCancel={onCancel}
|
||||
queries={queriesWorkingDraft}
|
||||
sources={this.formatSources}
|
||||
onSave={this.handleSaveCell}
|
||||
selected={this.findSelectedSource()}
|
||||
onSetQuerySource={this.handleSetQuerySource}
|
||||
isSavable={queriesWorkingDraft.every(isQuerySavable)}
|
||||
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
||||
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
||||
/>
|
||||
{isDisplayOptionsTabActive ? (
|
||||
<DisplayOptions
|
||||
queryConfigs={queriesWorkingDraft}
|
||||
onToggleStaticLegend={this.handleToggleStaticLegend}
|
||||
staticLegend={staticLegend}
|
||||
onResetFocus={this.handleResetFocus}
|
||||
/>
|
||||
) : (
|
||||
<QueryMaker
|
||||
source={this.getSource()}
|
||||
templates={templates}
|
||||
queries={queriesWorkingDraft}
|
||||
actions={queryActions}
|
||||
autoRefresh={autoRefresh}
|
||||
timeRange={timeRange}
|
||||
onDeleteQuery={this.handleDeleteQuery}
|
||||
onAddQuery={this.handleAddQuery}
|
||||
activeQueryIndex={activeQueryIndex}
|
||||
activeQuery={this.getActiveQuery()}
|
||||
setActiveQueryIndex={this.handleSetActiveQueryIndex}
|
||||
initialGroupByTime={AUTO_GROUP_BY}
|
||||
/>
|
||||
)}
|
||||
</CEOBottom>
|
||||
</ResizeContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CEOBottom = ({children}) => (
|
||||
<div className="overlay-technology--editor">{children}</div>
|
||||
)
|
||||
|
||||
const {arrayOf, func, node, number, shape, string} = PropTypes
|
||||
|
||||
CellEditorOverlay.propTypes = {
|
||||
onCancel: func.isRequired,
|
||||
onSave: func.isRequired,
|
||||
cell: shape({}).isRequired,
|
||||
templates: arrayOf(
|
||||
shape({
|
||||
tempVar: string.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
autoRefresh: number.isRequired,
|
||||
source: shape({
|
||||
links: shape({
|
||||
proxy: string.isRequired,
|
||||
queries: string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
editQueryStatus: func.isRequired,
|
||||
queryStatus: shape({
|
||||
queryID: string,
|
||||
status: shape({}),
|
||||
}).isRequired,
|
||||
dashboardID: string.isRequired,
|
||||
sources: arrayOf(shape()),
|
||||
thresholdsListType: string.isRequired,
|
||||
thresholdsListColors: colorsNumberSchema.isRequired,
|
||||
gaugeColors: colorsNumberSchema.isRequired,
|
||||
lineColors: colorsStringSchema.isRequired,
|
||||
}
|
||||
|
||||
CEOBottom.propTypes = {
|
||||
children: node,
|
||||
}
|
||||
|
||||
export default CellEditorOverlay
|
|
@ -82,7 +82,10 @@ const createWorkingDraft = (source: string, query: CellQuery): Query => {
|
|||
return draft
|
||||
}
|
||||
|
||||
const createWorkingDrafts = (source: string, queries: CellQuery[]): Query[] =>
|
||||
const createWorkingDrafts = (
|
||||
source: string,
|
||||
queries: CellQuery[] = []
|
||||
): Query[] =>
|
||||
_.cloneDeep(
|
||||
queries.map((query: CellQuery) => createWorkingDraft(source, query))
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue