Simplify schema explorer

pull/10616/head
Andrew Watkins 2018-05-04 11:31:27 -07:00
parent ccd060f179
commit 716f7e8b4d
8 changed files with 78 additions and 288 deletions

View File

@ -46,3 +46,25 @@ export const getDatabases = async () => {
throw error
}
}
export const getTags = async () => {
try {
const response = {data: {tags: ['tk1', 'tk2', 'tk3']}}
const {data} = await Promise.resolve(response)
return data.tags
} catch (error) {
console.error('Could not get tagKeys', error)
throw error
}
}
export const getTagValues = async () => {
try {
const response = {data: {values: ['tv1', 'tv2', 'tv3']}}
const {data} = await Promise.resolve(response)
return data.values
} catch (error) {
console.error('Could not get tagKeys', error)
throw error
}
}

View File

@ -1,34 +1,36 @@
import React, {PureComponent} from 'react'
import PropTypes from 'prop-types'
import _ from 'lodash'
import DatabaseListItem from 'src/ifql/components/DatabaseListItem'
import MeasurementList from 'src/ifql/components/MeasurementList'
import {Source} from 'src/types'
import {showDatabases} from 'src/shared/apis/metaQuery'
import showDatabasesParser from 'src/shared/parsing/showDatabases'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface DatabaseListProps {
db: string
source: Source
onChooseDatabase: (database: string) => void
}
interface DatabaseListState {
databases: string[]
measurement: string
db: string
}
const {shape} = PropTypes
@ErrorHandling
class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
class DatabaseList extends PureComponent<{}, DatabaseListState> {
public static contextTypes = {
source: shape({
links: shape({}).isRequired,
}).isRequired,
}
constructor(props) {
super(props)
this.state = {
databases: [],
measurement: '',
db: '',
}
}
@ -37,7 +39,7 @@ class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
}
public async getDatabases() {
const {source} = this.props
const {source} = this.context
try {
const {data} = await showDatabases(source.links.proxy)
@ -46,34 +48,31 @@ class DatabaseList extends PureComponent<DatabaseListProps, DatabaseListState> {
this.setState({databases: sorted})
const db = _.get(sorted, '0', '')
this.props.onChooseDatabase(db)
this.handleChooseDatabase(db)
} catch (err) {
console.error(err)
}
}
public render() {
const {onChooseDatabase} = this.props
return (
<div className="query-builder--column query-builder--column-db">
<div className="query-builder--list">
{this.state.databases.map(db => {
return (
<React.Fragment key={db}>
<DatabaseListItem
db={db}
isActive={this.props.db === db}
onChooseDatabase={onChooseDatabase}
/>
{this.props.db === db && <MeasurementList db={db} />}
</React.Fragment>
)
})}
</div>
<div className="ifql-schema-tree">
{this.state.databases.map(db => {
return (
<DatabaseListItem
db={db}
key={db}
onChooseDatabase={this.handleChooseDatabase}
/>
)
})}
</div>
)
}
private handleChooseDatabase = (db: string): void => {
this.setState({db})
}
}
export default DatabaseList

View File

@ -2,17 +2,22 @@ import React, {PureComponent} from 'react'
import classnames from 'classnames'
export interface Props {
isActive: boolean
import TagList from 'src/ifql/components/TagList'
interface Props {
db: string
onChooseDatabase: (db: string) => void
}
class DatabaseListItem extends PureComponent<Props> {
interface State {
isOpen: boolean
}
class DatabaseListItem extends PureComponent<Props, State> {
constructor(props) {
super(props)
this.state = {
measurement: '',
isOpen: false,
}
}
@ -21,23 +26,23 @@ class DatabaseListItem extends PureComponent<Props> {
return (
<div className={this.className} onClick={this.handleChooseDatabase}>
<span>
<div className="query-builder--caret icon caret-right" />
<div className="ifql-schema-item">
<div className="icon caret-right" />
{db}
</span>
</div>
{this.state.isOpen && <TagList db={db} />}
</div>
)
}
private get className(): string {
return classnames('query-builder--list-item', {
active: this.props.isActive,
return classnames('ifql-schema-tree', {
expanded: this.state.isOpen,
})
}
private handleChooseDatabase = () => {
const {onChooseDatabase, db} = this.props
onChooseDatabase(db)
this.setState({isOpen: !this.state.isOpen})
}
}

View File

@ -1,125 +0,0 @@
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 MeasurementListFilter from 'src/shared/components/MeasurementListFilter'
import MeasurementListItem from 'src/ifql/components/MeasurementListItem'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
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--sub-list">
{filtered.map(measurement => (
<MeasurementListItem
key={measurement}
db={this.props.db}
measurement={measurement}
selected={this.state.selected}
onChooseMeasurement={this.handleChooseMeasurement}
/>
))}
</div>
</div>
)
}
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

@ -1,50 +0,0 @@
import React, {PureComponent} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
import TagList from 'src/ifql/components/TagList'
interface Props {
db: string
selected: string
measurement: string
onChooseMeasurement: (measurement: string) => void
}
interface State {
isOpen: boolean
}
@ErrorHandling
class MeasurementListItem extends PureComponent<Props, State> {
constructor(props) {
super(props)
this.state = {isOpen: false}
}
public render() {
const {measurement, db} = 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>
{this.shouldShow && <TagList db={db} measurement={measurement} />}
</div>
)
}
private handleClick = () => {
const {measurement, onChooseMeasurement} = this.props
onChooseMeasurement(measurement)
}
private get shouldShow(): boolean {
return this.state.isOpen
}
}
export default MeasurementListItem

View File

@ -1,42 +1,14 @@
import React, {PureComponent} from 'react'
import PropTypes from 'prop-types'
import DatabaseList from 'src/ifql/components/DatabaseList'
interface State {
db: string
}
const {shape} = PropTypes
class SchemaExplorer extends PureComponent<{}, State> {
public static contextTypes = {
source: shape({
links: shape({}).isRequired,
}).isRequired,
}
constructor(props) {
super(props)
this.state = {
db: '',
}
}
class SchemaExplorer extends PureComponent {
public render() {
return (
<div className="ifql-schema-explorer">
<DatabaseList
db={this.state.db}
source={this.context.source}
onChooseDatabase={this.handleChooseDatabase}
/>
<DatabaseList />
</div>
)
}
private handleChooseDatabase = (db: string): void => {
this.setState({db})
}
}
export default SchemaExplorer

View File

@ -5,16 +5,13 @@ import _ from 'lodash'
import TagListItem from 'src/ifql/components/TagListItem'
import {showTagKeys, showTagValues} from 'src/shared/apis/metaQuery'
import showTagKeysParser from 'src/shared/parsing/showTagKeys'
import showTagValuesParser from 'src/shared/parsing/showTagValues'
import {getTags, getTagValues} from 'src/ifql/apis'
import {ErrorHandling} from 'src/shared/decorators/errors'
const {shape} = PropTypes
interface Props {
db: string
measurement: string
}
interface State {
@ -39,24 +36,8 @@ class TagList extends PureComponent<Props, State> {
}
public componentDidMount() {
const {db, measurement} = this.props
if (!db || !measurement) {
return
}
this.getTags()
}
public componentDidUpdate(prevProps) {
const {db, measurement} = this.props
const {db: prevDB, measurement: prevMeas} = prevProps
if (!db || !measurement) {
return
}
if (db === prevDB && measurement === prevMeas) {
const {db} = this.props
if (!db) {
return
}
@ -64,29 +45,14 @@ class TagList extends PureComponent<Props, State> {
}
public async getTags() {
const {db, measurement} = this.props
const {source} = this.context
const keys = await getTags()
const values = await getTagValues()
const {data} = await showTagKeys({
database: db,
measurement,
retentionPolicy: 'autogen',
source: source.links.proxy,
})
const {tagKeys} = showTagKeysParser(data)
const response = await showTagValues({
database: db,
measurement,
retentionPolicy: 'autogen',
source: source.links.proxy,
tagKeys,
const tags = keys.map(k => {
return (this.state.tags[k] = values)
})
const {tags} = showTagValuesParser(response.data)
const selected = Object.keys(tags)
this.setState({tags, selectedTag: selected[0]})
this.setState({tags})
}
public render() {

View File

@ -5,5 +5,6 @@
@import '../components/time-machine/ifql-editor';
@import '../components/time-machine/ifql-builder';
// @import '../components/time-machine/ifql-explorer';
@import '../components/time-machine/visualization';
@import '../components/time-machine/add-func-button';
@import '../components/time-machine/add-func-button';