Replace separate CSV manual and file entry dropdowns with one builder type that accepts both
Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com>feature/upload-template-var-csv
parent
707bb9b16d
commit
db3cca42fd
|
@ -1,94 +0,0 @@
|
|||
import React, {PureComponent, ChangeEvent} from 'react'
|
||||
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import TemplatePreviewList from 'src/tempVars/components/TemplatePreviewList'
|
||||
|
||||
import {TemplateBuilderProps, TemplateValueType, TemplateValue} from 'src/types'
|
||||
|
||||
interface State {
|
||||
templateValues: string[]
|
||||
templateValuesString: string
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class CSVManualTemplateBuilder extends PureComponent<
|
||||
TemplateBuilderProps,
|
||||
State
|
||||
> {
|
||||
public constructor(props: TemplateBuilderProps) {
|
||||
super(props)
|
||||
|
||||
const templateValues = props.template.values.map(v => v.value)
|
||||
|
||||
this.state = {
|
||||
templateValues,
|
||||
templateValuesString: templateValues.join(', '),
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {templateValues, templateValuesString} = this.state
|
||||
const pluralizer = templateValues.length === 1 ? '' : 's'
|
||||
|
||||
return (
|
||||
<div className="temp-builder csv-temp-builder">
|
||||
<div className="form-group">
|
||||
<label>Comma Separated Values</label>
|
||||
<div className="temp-builder--mq-controls">
|
||||
<textarea
|
||||
className="form-control"
|
||||
value={templateValuesString}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.handleBlur}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="temp-builder-results">
|
||||
<p>
|
||||
CSV contains <strong>{templateValues.length}</strong> value{
|
||||
pluralizer
|
||||
}
|
||||
</p>
|
||||
{templateValues.length > 0 && (
|
||||
<TemplatePreviewList items={templateValues} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private handleChange = (e: ChangeEvent<HTMLTextAreaElement>): void => {
|
||||
this.setState({templateValuesString: e.target.value})
|
||||
}
|
||||
|
||||
private handleBlur = (): void => {
|
||||
const {template, onUpdateTemplate} = this.props
|
||||
const {templateValuesString} = this.state
|
||||
|
||||
let templateValues
|
||||
|
||||
if (templateValuesString.trim() === '') {
|
||||
templateValues = []
|
||||
} else {
|
||||
templateValues = templateValuesString.split(',').map(s => s.trim())
|
||||
}
|
||||
|
||||
this.setState({templateValues})
|
||||
|
||||
const nextValues = templateValues.map((value: string): TemplateValue => {
|
||||
return {
|
||||
type: TemplateValueType.CSV,
|
||||
value,
|
||||
selected: false,
|
||||
}
|
||||
})
|
||||
|
||||
if (nextValues.length > 0) {
|
||||
nextValues[0].selected = true
|
||||
}
|
||||
|
||||
onUpdateTemplate({...template, values: nextValues})
|
||||
}
|
||||
}
|
||||
|
||||
export default CSVManualTemplateBuilder
|
|
@ -1,4 +1,4 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import React, {PureComponent, ChangeEvent} from 'react'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import TemplatePreviewList from 'src/tempVars/components/TemplatePreviewList'
|
||||
import DragAndDrop from 'src/shared/components/DragAndDrop'
|
||||
|
@ -12,10 +12,7 @@ interface State {
|
|||
}
|
||||
|
||||
@ErrorHandling
|
||||
class CSVFileTemplateBuilder extends PureComponent<
|
||||
TemplateBuilderProps,
|
||||
State
|
||||
> {
|
||||
class CSVTemplateBuilder extends PureComponent<TemplateBuilderProps, State> {
|
||||
public constructor(props: TemplateBuilderProps) {
|
||||
super(props)
|
||||
const templateValues = props.template.values.map(v => v.value)
|
||||
|
@ -27,7 +24,7 @@ class CSVFileTemplateBuilder extends PureComponent<
|
|||
}
|
||||
|
||||
public render() {
|
||||
const {templateValues} = this.state
|
||||
const {templateValues, templateValuesString} = this.state
|
||||
const pluralizer = templateValues.length === 1 ? '' : 's'
|
||||
return (
|
||||
<>
|
||||
|
@ -36,6 +33,19 @@ class CSVFileTemplateBuilder extends PureComponent<
|
|||
fileTypesToAccept={this.validFileExtension}
|
||||
handleSubmit={this.handleUploadFile}
|
||||
/>
|
||||
<div className="temp-builder csv-temp-builder" style={{zIndex: 9010}}>
|
||||
<div className="form-group" style={{zIndex: 9010}}>
|
||||
<label>Comma Separated Values</label>
|
||||
<div className="temp-builder--mq-controls">
|
||||
<textarea
|
||||
className="form-control"
|
||||
value={templateValuesString}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.handleBlur}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="temp-builder-results">
|
||||
<p>
|
||||
CSV contains <strong>{templateValues.length}</strong> value{
|
||||
|
@ -61,17 +71,34 @@ class CSVFileTemplateBuilder extends PureComponent<
|
|||
this.props.notify(notifyCSVUploadFailed())
|
||||
return
|
||||
}
|
||||
|
||||
let templateValues
|
||||
|
||||
if (uploadContent.trim() === '') {
|
||||
templateValues = []
|
||||
} else {
|
||||
templateValues = uploadContent.split(',').map(s => s.trim())
|
||||
}
|
||||
// account for newline separated values too.
|
||||
// should return values be strings only.
|
||||
|
||||
this.setState({templateValuesString: uploadContent})
|
||||
|
||||
const nextValues = this.getValuesFromString(uploadContent)
|
||||
|
||||
onUpdateTemplate({...template, values: nextValues})
|
||||
}
|
||||
|
||||
private get validFileExtension(): string {
|
||||
return '.csv'
|
||||
}
|
||||
|
||||
private handleChange = (e: ChangeEvent<HTMLTextAreaElement>): void => {
|
||||
this.setState({templateValuesString: e.target.value})
|
||||
}
|
||||
|
||||
private getValuesFromString(templateValuesString) {
|
||||
// trim whitepsace, return array of values
|
||||
let templateValues
|
||||
|
||||
if (templateValuesString.trim() === '') {
|
||||
templateValues = []
|
||||
} else {
|
||||
templateValues = templateValuesString.split(',').map(s => s.trim())
|
||||
}
|
||||
|
||||
this.setState({templateValues})
|
||||
|
||||
const nextValues = templateValues.map((value: string): TemplateValue => {
|
||||
|
@ -86,12 +113,17 @@ class CSVFileTemplateBuilder extends PureComponent<
|
|||
nextValues[0].selected = true
|
||||
}
|
||||
|
||||
onUpdateTemplate({...template, values: nextValues})
|
||||
return nextValues
|
||||
}
|
||||
|
||||
private get validFileExtension(): string {
|
||||
return '.csv'
|
||||
private handleBlur = (): void => {
|
||||
const {template, onUpdateTemplate} = this.props
|
||||
const {templateValuesString} = this.state
|
||||
|
||||
const nextValues = this.getValuesFromString(templateValuesString)
|
||||
|
||||
onUpdateTemplate({...template, values: nextValues})
|
||||
}
|
||||
}
|
||||
|
||||
export default CSVFileTemplateBuilder
|
||||
export default CSVTemplateBuilder
|
|
@ -14,8 +14,7 @@ import {getDeep} from 'src/utils/wrappers'
|
|||
import {notify as notifyActionCreator} from 'src/shared/actions/notifications'
|
||||
|
||||
import DatabasesTemplateBuilder from 'src/tempVars/components/DatabasesTemplateBuilder'
|
||||
import CSVManualTemplateBuilder from 'src/tempVars/components/CSVManualTemplateBuilder'
|
||||
import CSVFileTemplateBuilder from 'src/tempVars/components/CSVFileTemplateBuilder'
|
||||
import CSVTemplateBuilder from 'src/tempVars/components/CSVTemplateBuilder'
|
||||
import MeasurementsTemplateBuilder from 'src/tempVars/components/MeasurementsTemplateBuilder'
|
||||
import FieldKeysTemplateBuilder from 'src/tempVars/components/FieldKeysTemplateBuilder'
|
||||
import TagKeysTemplateBuilder from 'src/tempVars/components/TagKeysTemplateBuilder'
|
||||
|
@ -25,7 +24,6 @@ import MetaQueryTemplateBuilder from 'src/tempVars/components/MetaQueryTemplateB
|
|||
import {
|
||||
Template,
|
||||
TemplateType,
|
||||
BuilderType,
|
||||
TemplateBuilderProps,
|
||||
Source,
|
||||
RemoteDataState,
|
||||
|
@ -57,14 +55,13 @@ interface State {
|
|||
}
|
||||
|
||||
const TEMPLATE_BUILDERS = {
|
||||
[BuilderType.Databases]: DatabasesTemplateBuilder,
|
||||
[BuilderType.CSVManual]: CSVManualTemplateBuilder,
|
||||
[BuilderType.CSVFile]: CSVFileTemplateBuilder,
|
||||
[BuilderType.Measurements]: MeasurementsTemplateBuilder,
|
||||
[BuilderType.FieldKeys]: FieldKeysTemplateBuilder,
|
||||
[BuilderType.TagKeys]: TagKeysTemplateBuilder,
|
||||
[BuilderType.TagValues]: TagValuesTemplateBuilder,
|
||||
[BuilderType.MetaQuery]: MetaQueryTemplateBuilder,
|
||||
[TemplateType.Databases]: DatabasesTemplateBuilder,
|
||||
[TemplateType.CSV]: CSVTemplateBuilder,
|
||||
[TemplateType.Measurements]: MeasurementsTemplateBuilder,
|
||||
[TemplateType.FieldKeys]: FieldKeysTemplateBuilder,
|
||||
[TemplateType.TagKeys]: TagKeysTemplateBuilder,
|
||||
[TemplateType.TagValues]: TagValuesTemplateBuilder,
|
||||
[TemplateType.MetaQuery]: MetaQueryTemplateBuilder,
|
||||
}
|
||||
|
||||
const formatName = name => `:${name.replace(/:/g, '')}:`
|
||||
|
@ -175,15 +172,13 @@ class TemplateVariableEditor extends PureComponent<Props, State> {
|
|||
|
||||
private get templateBuilder(): ComponentClass<TemplateBuilderProps> {
|
||||
const {
|
||||
nextTemplate: {builderType},
|
||||
nextTemplate: {type},
|
||||
} = this.state
|
||||
|
||||
const component = TEMPLATE_BUILDERS[builderType]
|
||||
const component = TEMPLATE_BUILDERS[type]
|
||||
|
||||
if (!component) {
|
||||
throw new Error(
|
||||
`Could not find template builder for type "${builderType}"`
|
||||
)
|
||||
throw new Error(`Could not find template builder for type "${type}"`)
|
||||
}
|
||||
|
||||
return component
|
||||
|
@ -193,13 +188,13 @@ class TemplateVariableEditor extends PureComponent<Props, State> {
|
|||
this.setState({nextTemplate})
|
||||
}
|
||||
|
||||
private handleChooseType = ({builderType}) => {
|
||||
private handleChooseType = ({type}) => {
|
||||
const {
|
||||
nextTemplate: {id, tempVar},
|
||||
} = this.state
|
||||
|
||||
const nextNextTemplate = {
|
||||
...DEFAULT_TEMPLATES[builderType](),
|
||||
...DEFAULT_TEMPLATES[type](),
|
||||
id,
|
||||
tempVar,
|
||||
}
|
||||
|
@ -290,11 +285,11 @@ class TemplateVariableEditor extends PureComponent<Props, State> {
|
|||
|
||||
private get dropdownSelection(): string {
|
||||
const {
|
||||
nextTemplate: {builderType},
|
||||
nextTemplate: {type},
|
||||
} = this.state
|
||||
|
||||
return getDeep(
|
||||
TEMPLATE_TYPES_LIST.filter(t => t.builderType === builderType),
|
||||
TEMPLATE_TYPES_LIST.filter(t => t.type === type),
|
||||
'0.text',
|
||||
''
|
||||
)
|
||||
|
|
|
@ -2,54 +2,41 @@ import uuid from 'uuid'
|
|||
|
||||
import {TimeRange} from 'src/types/query'
|
||||
import {TEMP_VAR_DASHBOARD_TIME} from 'src/shared/constants'
|
||||
import {Template, TemplateType, TemplateValueType, BuilderType} from 'src/types'
|
||||
import {Template, TemplateType, TemplateValueType} from 'src/types'
|
||||
|
||||
interface TemplateTypesListItem {
|
||||
text: string
|
||||
type: TemplateType
|
||||
builderType: BuilderType
|
||||
}
|
||||
|
||||
export const TEMPLATE_TYPES_LIST: TemplateTypesListItem[] = [
|
||||
{
|
||||
text: 'Databases',
|
||||
type: TemplateType.Databases,
|
||||
builderType: BuilderType.Databases,
|
||||
},
|
||||
{
|
||||
text: 'Measurements',
|
||||
type: TemplateType.Measurements,
|
||||
builderType: BuilderType.Measurements,
|
||||
},
|
||||
{
|
||||
text: 'Field Keys',
|
||||
type: TemplateType.FieldKeys,
|
||||
builderType: BuilderType.FieldKeys,
|
||||
},
|
||||
{
|
||||
text: 'Tag Keys',
|
||||
type: TemplateType.TagKeys,
|
||||
builderType: BuilderType.TagKeys,
|
||||
},
|
||||
{
|
||||
text: 'Tag Values',
|
||||
type: TemplateType.TagValues,
|
||||
builderType: BuilderType.TagValues,
|
||||
},
|
||||
{
|
||||
text: 'CSV (Manual Entry)',
|
||||
type: TemplateType.CSV,
|
||||
builderType: BuilderType.CSVManual,
|
||||
},
|
||||
{
|
||||
text: 'CSV',
|
||||
type: TemplateType.CSV,
|
||||
builderType: BuilderType.CSVFile,
|
||||
},
|
||||
{
|
||||
text: 'Custom Meta Query',
|
||||
type: TemplateType.MetaQuery,
|
||||
builderType: BuilderType.MetaQuery,
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -77,7 +64,7 @@ interface DefaultTemplates {
|
|||
}
|
||||
|
||||
export const DEFAULT_TEMPLATES: DefaultTemplates = {
|
||||
[BuilderType.Databases]: () => {
|
||||
[TemplateType.Databases]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
|
@ -89,20 +76,18 @@ export const DEFAULT_TEMPLATES: DefaultTemplates = {
|
|||
},
|
||||
],
|
||||
type: TemplateType.Databases,
|
||||
builderType: BuilderType.Databases,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: TEMPLATE_VARIABLE_QUERIES[TemplateType.Databases],
|
||||
},
|
||||
}
|
||||
},
|
||||
[BuilderType.Measurements]: () => {
|
||||
[TemplateType.Measurements]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
type: TemplateType.Measurements,
|
||||
builderType: BuilderType.Measurements,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: TEMPLATE_VARIABLE_QUERIES[TemplateType.Measurements],
|
||||
|
@ -110,74 +95,58 @@ export const DEFAULT_TEMPLATES: DefaultTemplates = {
|
|||
},
|
||||
}
|
||||
},
|
||||
[BuilderType.CSVManual]: () => {
|
||||
[TemplateType.CSV]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
builderType: BuilderType.CSVManual,
|
||||
type: TemplateType.CSV,
|
||||
label: '',
|
||||
query: {},
|
||||
}
|
||||
},
|
||||
[BuilderType.CSVFile]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
builderType: BuilderType.CSVFile,
|
||||
type: TemplateType.CSV,
|
||||
label: '',
|
||||
query: {},
|
||||
}
|
||||
},
|
||||
[BuilderType.TagKeys]: () => {
|
||||
[TemplateType.TagKeys]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
type: TemplateType.TagKeys,
|
||||
builderType: BuilderType.TagKeys,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: TEMPLATE_VARIABLE_QUERIES[TemplateType.TagKeys],
|
||||
},
|
||||
}
|
||||
},
|
||||
[BuilderType.FieldKeys]: () => {
|
||||
[TemplateType.FieldKeys]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
type: TemplateType.FieldKeys,
|
||||
builderType: BuilderType.FieldKeys,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: TEMPLATE_VARIABLE_QUERIES[TemplateType.FieldKeys],
|
||||
},
|
||||
}
|
||||
},
|
||||
[BuilderType.TagValues]: () => {
|
||||
[TemplateType.TagValues]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: '',
|
||||
values: [],
|
||||
type: TemplateType.TagValues,
|
||||
builderType: BuilderType.TagValues,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: TEMPLATE_VARIABLE_QUERIES[TemplateType.TagValues],
|
||||
},
|
||||
}
|
||||
},
|
||||
[BuilderType.MetaQuery]: () => {
|
||||
[TemplateType.MetaQuery]: () => {
|
||||
return {
|
||||
id: uuid.v4(),
|
||||
tempVar: ':my-meta-query:',
|
||||
values: [],
|
||||
type: TemplateType.MetaQuery,
|
||||
builderType: BuilderType.MetaQuery,
|
||||
label: '',
|
||||
query: {
|
||||
influxql: '',
|
||||
|
|
|
@ -8,7 +8,6 @@ import {
|
|||
TemplateValue,
|
||||
URLQueryParams,
|
||||
TemplateType,
|
||||
BuilderType,
|
||||
TemplateValueType,
|
||||
TemplateUpdate,
|
||||
TemplateBuilderProps,
|
||||
|
@ -107,7 +106,6 @@ export {
|
|||
JSONFeedData,
|
||||
AnnotationInterface,
|
||||
TemplateType,
|
||||
BuilderType,
|
||||
TemplateValueType,
|
||||
TemplateUpdate,
|
||||
TemplateBuilderProps,
|
||||
|
|
|
@ -40,26 +40,12 @@ export enum TemplateType {
|
|||
MetaQuery = 'influxql',
|
||||
}
|
||||
|
||||
export enum BuilderType {
|
||||
AutoGroupBy = 'autoGroupBy',
|
||||
Constant = 'constant',
|
||||
FieldKeys = 'fieldKeys',
|
||||
Measurements = 'measurements',
|
||||
TagKeys = 'tagKeys',
|
||||
TagValues = 'tagValues',
|
||||
CSVManual = 'csvManual',
|
||||
CSVFile = 'csvFile',
|
||||
Databases = 'databases',
|
||||
MetaQuery = 'influxql',
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
id: string
|
||||
tempVar: string
|
||||
values: TemplateValue[]
|
||||
type: TemplateType
|
||||
label: string
|
||||
builderType?: BuilderType
|
||||
query?: TemplateQuery
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
QueryConfig,
|
||||
TemplateType,
|
||||
TemplateValueType,
|
||||
BuilderType,
|
||||
} from 'src/types'
|
||||
import {
|
||||
Axes,
|
||||
|
@ -205,7 +204,6 @@ export const userDefinedTemplateVariables: Template[] = [
|
|||
{
|
||||
tempVar: ':fields:',
|
||||
type: TemplateType.FieldKeys,
|
||||
builderType: BuilderType.FieldKeys,
|
||||
label: '',
|
||||
values: [
|
||||
{
|
||||
|
@ -264,7 +262,6 @@ export const userDefinedTemplateVariables: Template[] = [
|
|||
{
|
||||
tempVar: ':measurements:',
|
||||
type: TemplateType.Measurements,
|
||||
builderType: BuilderType.Measurements,
|
||||
label: '',
|
||||
values: [
|
||||
{
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import {Source, Template, Dashboard, Cell, CellType} from 'src/types'
|
||||
import {
|
||||
SourceLinks,
|
||||
TemplateType,
|
||||
BuilderType,
|
||||
TemplateValueType,
|
||||
} from 'src/types'
|
||||
import {SourceLinks, TemplateType, TemplateValueType} from 'src/types'
|
||||
|
||||
export const role = {
|
||||
name: '',
|
||||
|
@ -596,7 +591,6 @@ export const hosts = {
|
|||
export const template: Template = {
|
||||
id: '1',
|
||||
type: TemplateType.TagKeys,
|
||||
builderType: BuilderType.TagKeys,
|
||||
label: 'test query',
|
||||
tempVar: ':region:',
|
||||
query: {
|
||||
|
|
|
@ -3,7 +3,7 @@ import {shallow} from 'enzyme'
|
|||
|
||||
import TemplateControlBar from 'src/tempVars/components/TemplateControlBar'
|
||||
import TemplateControlDropdown from 'src/tempVars/components/TemplateControlDropdown'
|
||||
import {TemplateType, TemplateValueType, BuilderType} from 'src/types'
|
||||
import {TemplateType, TemplateValueType} from 'src/types'
|
||||
import {source} from 'test/resources'
|
||||
|
||||
const defaultProps = {
|
||||
|
@ -14,7 +14,6 @@ const defaultProps = {
|
|||
tempVar: ':alpha:',
|
||||
label: '',
|
||||
type: TemplateType.Constant,
|
||||
builderType: BuilderType.Constant,
|
||||
values: [
|
||||
{
|
||||
value: 'firstValue',
|
||||
|
|
Loading…
Reference in New Issue