Introduce MeasurementList to schema explorer

pull/10616/head
Andrew Watkins 2018-05-02 18:04:25 -07:00
parent 7c40c417dc
commit 96ffc67d76
4 changed files with 217 additions and 16 deletions

View File

@ -1,7 +1,9 @@
import React, {PureComponent} from 'react'
import _ from 'lodash'
import uuid from 'uuid'
import DatabaseListItem from 'src/ifql/components/DatabaseListItem'
import MeasurementList from 'src/ifql/components/MeasurementList'
import {Source} from 'src/types'
@ -18,6 +20,7 @@ interface DatabaseListProps {
interface DatabaseListState {
databases: string[]
measurement: string
}
@ErrorHandling
@ -26,6 +29,7 @@ class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
super(props)
this.state = {
databases: [],
measurement: '',
}
}
@ -39,15 +43,7 @@ class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
try {
const {data} = await showDatabases(source.links.proxy)
const {databases} = showDatabasesParser(data)
const dbs = databases.map(database => {
if (database === '_internal') {
return `${database}.monitor`
}
return `${database}.autogen`
})
const sorted = dbs.sort()
const sorted = databases.sort()
this.setState({databases: sorted})
const db = _.get(sorted, '0', '')
@ -65,12 +61,21 @@ class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
<div className="query-builder--list">
{this.state.databases.map(db => {
return (
<DatabaseListItem
key={db}
db={db}
isActive={this.props.db === db}
onChooseDatabase={onChooseDatabase}
/>
<>
<DatabaseListItem
key={uuid.v4()}
db={db}
isActive={this.props.db === db}
onChooseDatabase={onChooseDatabase}
/>
{this.props.db === db && (
<MeasurementList
key={uuid.v4()}
db={db}
onChooseMeasurement={this.handleChooseMeasurement}
/>
)}
</>
)
})}
</div>

View File

@ -9,10 +9,19 @@ export interface Props {
}
class DatabaseListItem extends PureComponent<Props> {
constructor(props) {
super(props)
this.state = {
measurement: '',
}
}
public render() {
const {db} = this.props
return (
<div className={this.className} onClick={this.handleChooseDatabase}>
{this.props.db}
{db}
</div>
)
}

View File

@ -0,0 +1,131 @@
import React, {PureComponent} from 'react'
import PropTypes from 'prop-types'
import {showMeasurements} from 'src/shared/apis/metaQuery'
import showMeasurementsParser from 'src/shared/parsing/showMeasurements'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import MeasurementListFilter from 'src/shared/components/MeasurementListFilter'
import MeasurementListItem from 'src/shared/components/MeasurementListItem'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
onChooseMeasurement: (measurement: string) => void
db: string
}
interface State {
measurements: string[]
filterText: string
filtered: string[]
selected: string
}
const {shape} = PropTypes
@ErrorHandling
class MeasurementList extends PureComponent<Props, State> {
public static contextTypes = {
source: shape({
links: shape({}).isRequired,
}).isRequired,
}
constructor(props) {
super(props)
this.state = {
filterText: '',
filtered: [],
measurements: [],
selected: '',
}
}
public componentDidMount() {
if (!this.props.db) {
return
}
this.getMeasurements()
}
public render() {
const {filtered} = this.state
return (
<div className="query-builder--column">
<div className="query-builder--heading">
<span>Measurements & Tags</span>
<MeasurementListFilter
onEscape={this.handleEscape}
onFilterText={this.handleFilterText}
filterText={this.state.filterText}
/>
</div>
<div className="query-builder--list">
{filtered.map(measurement => (
<MeasurementListItem
key={measurement}
measurement={measurement}
selected={this.state.selected}
onChooseTag={this.handleChooseTag}
onChooseMeasurement={this.handleChooseMeasurement}
/>
))}
</div>
</div>
)
}
private handleChooseTag = () => {
console.log('Choose a tag')
}
private async getMeasurements() {
const {source} = this.context
const {db} = this.props
try {
const {data} = await showMeasurements(source.links.proxy, db)
const {measurementSets} = showMeasurementsParser(data)
const measurements = measurementSets[0].measurements
const selected = measurements[0]
this.setState({measurements, filtered: measurements, selected})
} catch (err) {
console.error(err)
}
}
private handleChooseMeasurement = (selected: string): void => {
this.setState({selected})
}
private handleFilterText = e => {
e.stopPropagation()
const filterText = e.target.value
this.setState({
filterText,
filtered: this.handleFilterMeasuremet(filterText),
})
}
private handleFilterMeasuremet = filter => {
return this.state.measurements.filter(m =>
m.toLowerCase().includes(filter.toLowerCase())
)
}
private handleEscape = e => {
if (e.key !== 'Escape') {
return
}
e.stopPropagation()
this.setState({
filterText: '',
})
}
}
export default MeasurementList

View File

@ -0,0 +1,56 @@
import React, {PureComponent} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
selected: string
measurement: string
onChooseTag: () => void
onChooseMeasurement: (measurement: string) => void
}
interface State {
isOpen: boolean
}
@ErrorHandling
class MeasurementListItem extends PureComponent<Props, State> {
constructor(props) {
super(props)
this.state = {isOpen: this.isCurrentMeasurement}
}
public render() {
const {measurement} = this.props
return (
<div key={measurement} onClick={this.handleClick}>
<div className="query-builder--list-item">
<span>
<div className="query-builder--caret icon caret-right" />
{measurement}
</span>
</div>
</div>
)
}
private handleClick = () => {
const {measurement, onChooseMeasurement} = this.props
if (!this.isCurrentMeasurement) {
this.setState({isOpen: true}, () => {
onChooseMeasurement(measurement)
})
} else {
this.setState({isOpen: !this.state.isOpen})
}
}
private get isCurrentMeasurement(): boolean {
const {selected, measurement} = this.props
return selected === measurement
}
}
export default MeasurementListItem