commit
789d3d7f1e
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,57 +62,95 @@ 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
|
||||||
|
|
||||||
return sources.reduce((acc, source) => {
|
const sourceOptions = sources.reduce((acc, source) => {
|
||||||
const servicesForSource = services.filter(service => {
|
let items = []
|
||||||
return service.sourceID === source.id
|
if (allowFlux) {
|
||||||
})
|
items = [...items, ...this.fluxSourceItems(source)]
|
||||||
|
}
|
||||||
const serviceItems = servicesForSource.map(service => {
|
|
||||||
const serviceDropdownItem: SourceDropdownItem = {
|
|
||||||
sourceID: source.id,
|
|
||||||
serviceID: service.id,
|
|
||||||
links: service.links,
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Dropdown.Item
|
|
||||||
key={`${source.id}-${service.id}`}
|
|
||||||
id={`${source.id}-${service.id}`}
|
|
||||||
value={serviceDropdownItem}
|
|
||||||
>
|
|
||||||
{`${source.name} / ${service.name} (flux)`}
|
|
||||||
</Dropdown.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (allowInfluxQL) {
|
if (allowInfluxQL) {
|
||||||
const sourceDropdownItem: SourceDropdownItem = {
|
items = [...items, this.influxQLSourceItem(source)]
|
||||||
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]
|
|
||||||
|
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
|
||||||
|
|
||||||
|
const servicesForSource = services.filter(service => {
|
||||||
|
return service.sourceID === source.id
|
||||||
|
})
|
||||||
|
return servicesForSource.map(service => {
|
||||||
|
const serviceDropdownItem: SourceDropdownItem = {
|
||||||
|
sourceID: source.id,
|
||||||
|
serviceID: service.id,
|
||||||
|
links: service.links,
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Dropdown.Item
|
||||||
|
key={`${source.id}-${service.id}`}
|
||||||
|
id={`${source.id}-${service.id}`}
|
||||||
|
value={serviceDropdownItem}
|
||||||
|
>
|
||||||
|
{`${source.name} / ${service.name} (flux)`}
|
||||||
|
</Dropdown.Item>
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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}`
|
||||||
|
|
|
@ -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 = () => {
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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',
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue