Simplify schema explorer
parent
ccd060f179
commit
716f7e8b4d
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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';
|
Loading…
Reference in New Issue