Merge pull request #4254 from influxdata/flux/dynamic-sources

Flux/dynamic sources
pull/4269/head
Iris Scholten 2018-08-20 21:30:24 -07:00 committed by GitHub
commit 789d3d7f1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 164 additions and 55 deletions

View File

@ -5,6 +5,7 @@
1. [#4220](https://github.com/influxdata/chronograf/pull/4220): Add ability to copy expanded/untruncated log message 1. [#4220](https://github.com/influxdata/chronograf/pull/4220): Add ability to copy expanded/untruncated log message
1. [#4228](https://github.com/influxdata/chronograf/pull/4228): Add close button for logs pop over 1. [#4228](https://github.com/influxdata/chronograf/pull/4228): Add close button for logs pop over
1. [#4241](https://github.com/influxdata/chronograf/pull/4241): Add search attributes to log viewer 1. [#4241](https://github.com/influxdata/chronograf/pull/4241): Add search attributes to log viewer
1. [#4254](https://github.com/influxdata/chronograf/pull/4254): Add Dynamic Source option to CEO source selector
### UI Improvements ### UI Improvements
1. [#4227](https://github.com/influxdata/chronograf/pull/4227): Redesign Cell Editor Overlay for reuse in other parts of application 1. [#4227](https://github.com/influxdata/chronograf/pull/4227): Redesign Cell Editor Overlay for reuse in other parts of application

View File

@ -1,7 +1,10 @@
// Libraries
import React, {SFC} from 'react' import React, {SFC} from 'react'
// Componentes
import SourceDropdown from 'src/flux/components/SourceDropdown' import SourceDropdown from 'src/flux/components/SourceDropdown'
// Types
import * as QueriesModels from 'src/types/queries' import * as QueriesModels from 'src/types/queries'
import * as SourcesModels from 'src/types/sources' import * as SourcesModels from 'src/types/sources'
import {Service} from 'src/types' import {Service} from 'src/types'
@ -12,6 +15,8 @@ interface Props {
service: Service service: Service
services: Service[] services: Service[]
queries: QueriesModels.QueryConfig[] queries: QueriesModels.QueryConfig[]
isDynamicSourceSelected: boolean
onSelectDynamicSource: () => void
onChangeService: (service: Service, source: SourcesModels.Source) => void onChangeService: (service: Service, source: SourcesModels.Source) => void
} }
@ -22,6 +27,8 @@ const SourceSelector: SFC<Props> = ({
services, services,
queries, queries,
onChangeService, onChangeService,
isDynamicSourceSelected,
onSelectDynamicSource,
}) => { }) => {
return sources.length > 1 && queries.length ? ( return sources.length > 1 && queries.length ? (
<div className="source-selector"> <div className="source-selector">
@ -32,7 +39,12 @@ const SourceSelector: SFC<Props> = ({
source={source} source={source}
sources={sources} sources={sources}
allowInfluxQL={true} allowInfluxQL={true}
// TODO: when flux is added into CEO/DE, change to true
allowFlux={false}
allowDynamicSource={true}
isDynamicSourceSelected={isDynamicSourceSelected}
onChangeService={onChangeService} onChangeService={onChangeService}
onSelectDynamicSource={onSelectDynamicSource}
/> />
</div> </div>
) : ( ) : (

View File

@ -41,6 +41,8 @@ class FluxHeader extends PureComponent<Props> {
services={services} services={services}
service={service} service={service}
allowInfluxQL={false} allowInfluxQL={false}
allowFlux={true}
allowDynamicSource={false}
onChangeService={onChangeService} onChangeService={onChangeService}
/> />
<button <button

View File

@ -1,7 +1,13 @@
// Libraries
import React, {PureComponent} from 'react' import React, {PureComponent} from 'react'
// Components
import Dropdown from 'src/reusable_ui/components/dropdowns/Dropdown' import Dropdown from 'src/reusable_ui/components/dropdowns/Dropdown'
// Constants
import {DynamicSource} from 'src/sources/constants'
// types
import {Service, Source, ServiceLinks, SourceLinks} from 'src/types' import {Service, Source, ServiceLinks, SourceLinks} from 'src/types'
interface Props { interface Props {
@ -10,6 +16,10 @@ interface Props {
services: Service[] services: Service[]
sources: Source[] sources: Source[]
allowInfluxQL: boolean allowInfluxQL: boolean
allowFlux: boolean
allowDynamicSource: boolean
isDynamicSourceSelected?: boolean
onSelectDynamicSource?: () => void
onChangeService: (service: Service, source: Source) => void onChangeService: (service: Service, source: Source) => void
} }
@ -32,8 +42,18 @@ class SourceDropdown extends PureComponent<Props> {
) )
} }
private handleSelect = (choice: SourceDropdownItem) => { private handleSelect = (choice: SourceDropdownItem): void => {
const {sources, services} = this.props const {
sources,
services,
onChangeService,
onSelectDynamicSource,
} = this.props
if (choice.sourceID === DynamicSource.id && onSelectDynamicSource) {
onSelectDynamicSource()
return
}
const source = sources.find(src => { const source = sources.find(src => {
return src.id === choice.sourceID return src.id === choice.sourceID
@ -42,18 +62,67 @@ class SourceDropdown extends PureComponent<Props> {
return s.id === choice.serviceID return s.id === choice.serviceID
}) })
this.props.onChangeService(service, source) onChangeService(service, source)
} }
private get dropdownItems(): JSX.Element[] { private get dropdownItems(): JSX.Element[] {
const {services, sources, allowInfluxQL} = this.props const {sources, allowFlux, allowInfluxQL, allowDynamicSource} = this.props
const sourceOptions = sources.reduce((acc, source) => {
let items = []
if (allowFlux) {
items = [...items, ...this.fluxSourceItems(source)]
}
if (allowInfluxQL) {
items = [...items, this.influxQLSourceItem(source)]
}
return [...acc, ...items]
}, [])
if (allowDynamicSource) {
return [...sourceOptions, this.dynamicSourceOption]
}
return sourceOptions
}
private get dynamicSourceOption(): JSX.Element {
const dynamicSourceDropdownItem = {
sourceID: DynamicSource.id,
}
return (
<Dropdown.Item
key={DynamicSource.id}
id={DynamicSource.id}
value={dynamicSourceDropdownItem}
>
{DynamicSource.name}
</Dropdown.Item>
)
}
private influxQLSourceItem(source: Source): JSX.Element {
const sourceDropdownItem: SourceDropdownItem = {
sourceID: source.id,
links: source.links,
}
return (
<Dropdown.Item key={source.id} id={source.id} value={sourceDropdownItem}>
{`${source.name} (InfluxQL)`}
</Dropdown.Item>
)
}
private fluxSourceItems(source: Source): JSX.Element[] {
const {services} = this.props
return sources.reduce((acc, source) => {
const servicesForSource = services.filter(service => { const servicesForSource = services.filter(service => {
return service.sourceID === source.id return service.sourceID === source.id
}) })
return servicesForSource.map(service => {
const serviceItems = servicesForSource.map(service => {
const serviceDropdownItem: SourceDropdownItem = { const serviceDropdownItem: SourceDropdownItem = {
sourceID: source.id, sourceID: source.id,
serviceID: service.id, serviceID: service.id,
@ -69,30 +138,19 @@ class SourceDropdown extends PureComponent<Props> {
</Dropdown.Item> </Dropdown.Item>
) )
}) })
if (allowInfluxQL) {
const sourceDropdownItem: SourceDropdownItem = {
sourceID: source.id,
links: source.links,
}
const influxQLDropdownItem = (
<Dropdown.Item
key={source.id}
id={source.id}
value={sourceDropdownItem}
>
{`${source.name} (InfluxQL)`}
</Dropdown.Item>
)
return [...acc, ...serviceItems, influxQLDropdownItem]
}
return [...acc, ...serviceItems]
}, [])
} }
private get selectedID(): string { private get selectedID(): string {
const {service, source} = this.props const {
service,
source,
allowDynamicSource,
isDynamicSourceSelected,
} = this.props
if (allowDynamicSource && isDynamicSourceSelected) {
return DynamicSource.id
}
if (service) { if (service) {
return `${service.sourceID}-${service.id}` return `${service.sourceID}-${service.id}`

View File

@ -66,22 +66,29 @@ interface State {
activeEditorTab: CEOTabs activeEditorTab: CEOTabs
selectedSource: Source selectedSource: Source
selectedService: Service selectedService: Service
useDynamicSource: boolean
} }
class TimeMachine extends PureComponent<Props, State> { class TimeMachine extends PureComponent<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props) super(props)
const {queryDrafts} = props
const useDynamicSource = getDeep(queryDrafts, '0.source', '') === ''
this.state = { this.state = {
activeQueryIndex: 0, activeQueryIndex: 0,
activeEditorTab: CEOTabs.Queries, activeEditorTab: CEOTabs.Queries,
selectedService: null, selectedService: null,
selectedSource: null, selectedSource: null,
useDynamicSource,
} }
} }
public render() { public render() {
const {services} = this.props const {services} = this.props
const {useDynamicSource} = this.state
const horizontalDivisions = [ const horizontalDivisions = [
{ {
name: '', name: '',
@ -112,6 +119,8 @@ class TimeMachine extends PureComponent<Props, State> {
service={this.service} service={this.service}
services={services} services={services}
onChangeService={this.handleChangeService} onChangeService={this.handleChangeService}
onSelectDynamicSource={this.handleSelectDynamicSource}
isDynamicSourceSelected={useDynamicSource}
/> />
<div className="deceo--container"> <div className="deceo--container">
<Threesizer <Threesizer
@ -206,22 +215,25 @@ class TimeMachine extends PureComponent<Props, State> {
private get source(): Source { private get source(): Source {
const {source, sources, queryDrafts} = this.props const {source, sources, queryDrafts} = this.props
const {selectedSource} = this.state const {selectedSource, useDynamicSource} = this.state
if (selectedSource) { if (selectedSource) {
return selectedSource return selectedSource
} }
const query = _.get(queryDrafts, 0) // return current source
const querySource = _.get(query, 'source') if (useDynamicSource) {
if (!query || !querySource) {
return source return source
} }
const foundSource = sources.find( const queryDraft = _.get(queryDrafts, 0)
s => s.links.self === _.get(query, 'source', null) const querySource = _.get(queryDraft, 'source')
)
if (!queryDraft || !querySource) {
return source
}
const foundSource = sources.find(s => s.links.self === querySource)
if (foundSource) { if (foundSource) {
return foundSource return foundSource
} }
@ -356,10 +368,7 @@ class TimeMachine extends PureComponent<Props, State> {
} }
} }
private handleChangeService = ( private updateQueryDrafts(selectedSource: Source) {
selectedService: Service,
selectedSource: Source
) => {
const {queryDrafts, updateQueryDrafts} = this.props const {queryDrafts, updateQueryDrafts} = this.props
const queries: CellQuery[] = queryDrafts.map(q => { const queries: CellQuery[] = queryDrafts.map(q => {
@ -372,7 +381,23 @@ class TimeMachine extends PureComponent<Props, State> {
}) })
updateQueryDrafts(queries) updateQueryDrafts(queries)
this.setState({selectedService, selectedSource}) }
private handleChangeService = (
selectedService: Service,
selectedSource: Source
): void => {
const useDynamicSource = false
this.updateQueryDrafts(selectedSource)
this.setState({selectedService, selectedSource, useDynamicSource})
}
private handleSelectDynamicSource = (): void => {
const useDynamicSource = true
this.updateQueryDrafts(null)
this.setState({useDynamicSource})
} }
private handleAddQuery = () => { private handleAddQuery = () => {

View File

@ -11,8 +11,10 @@ interface Props {
sources: SourcesModels.SourceOption[] sources: SourcesModels.SourceOption[]
service: Service service: Service
services: Service[] services: Service[]
isDynamicSourceSelected: boolean
onChangeService: (service: Service, source: SourcesModels.Source) => void onChangeService: (service: Service, source: SourcesModels.Source) => void
queries: QueriesModels.QueryConfig[] queries: QueriesModels.QueryConfig[]
onSelectDynamicSource: () => void
} }
const TimeMachineControls: SFC<Props> = ({ const TimeMachineControls: SFC<Props> = ({
@ -22,6 +24,8 @@ const TimeMachineControls: SFC<Props> = ({
queries, queries,
services, services,
onChangeService, onChangeService,
isDynamicSourceSelected,
onSelectDynamicSource,
}) => { }) => {
return ( return (
<div className="deceo--controls"> <div className="deceo--controls">
@ -32,6 +36,8 @@ const TimeMachineControls: SFC<Props> = ({
services={services} services={services}
queries={queries} queries={queries}
onChangeService={onChangeService} onChangeService={onChangeService}
isDynamicSourceSelected={isDynamicSourceSelected}
onSelectDynamicSource={onSelectDynamicSource}
/> />
</div> </div>
) )

View File

@ -3,3 +3,8 @@ export const REQUIRED_ROLE_COPY =
export const KAPACITOR_TOOLTIP_COPY = export const KAPACITOR_TOOLTIP_COPY =
'<p>Kapacitor Connections are<br/>scoped per InfluxDB Connection.<br/>Only one can be active at a time.</p>' '<p>Kapacitor Connections are<br/>scoped per InfluxDB Connection.<br/>Only one can be active at a time.</p>'
export enum DynamicSource {
name = 'Dynamic Source',
id = 'dynamic',
}