diff --git a/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.test.tsx b/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.test.tsx index fc502de2d8..a077bd9e78 100644 --- a/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.test.tsx +++ b/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.test.tsx @@ -14,6 +14,7 @@ const setup = (override = {}) => { removeTagValue: jest.fn(), autoFocus: true, value: [], + helpText: '', ...override, } diff --git a/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.tsx b/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.tsx index f01224c756..643bf7cb3c 100644 --- a/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.tsx +++ b/ui/src/onboarding/components/configureStep/streaming/ArrayFormElement.tsx @@ -12,13 +12,15 @@ interface Props { removeTagValue: (item: string, fieldName: string) => void autoFocus: boolean value: string[] + helpText: string } class ConfigFieldSwitcher extends PureComponent { public render() { - const {fieldName, autoFocus} = this.props + const {fieldName, autoFocus, helpText} = this.props + return ( - + { +const setup = (override = {}, shouldMount = false) => { const props = { fieldName: '', fieldType: ConfigFieldType.String, @@ -20,10 +20,13 @@ const setup = (override = {}) => { removeTagValue: jest.fn(), index: 0, value: '', + isRequired: true, ...override, } - const wrapper = shallow() + const wrapper = shouldMount + ? mount() + : shallow() return {wrapper} } @@ -40,29 +43,89 @@ describe('Onboarding.Components.ConfigureStep.Streaming.ConfigFieldSwitcher', () expect(wrapper.exists()).toBe(true) expect(input.exists()).toBe(true) }) + + describe('if not required', () => { + it('optional is displayed as help text', () => { + const fieldName = 'yo' + const fieldType = ConfigFieldType.String + const value = '' + const {wrapper} = setup({ + fieldName, + fieldType, + isRequired: false, + value, + }) + + const input = wrapper.find(Input) + const formElement = wrapper.find(FormElement) + + expect(wrapper.exists()).toBe(true) + expect(input.exists()).toBe(true) + expect(formElement.prop('helpText')).toBe('optional') + }) + }) }) + describe('if type is array', () => { it('renders an array input', () => { const fieldName = ['yo'] const fieldType = ConfigFieldType.StringArray - const {wrapper} = setup({fieldName, fieldType}) + const value = [] + const {wrapper} = setup({fieldName, fieldType, value}, true) const input = wrapper.find(ArrayFormElement) + const formElement = wrapper.find(FormElement) + + expect(input.exists()).toBe(true) + expect(formElement.prop('helpText')).toBe('') + }) + + describe('if not required', () => { + const fieldName = ['yo'] + const value = [] + const fieldType = ConfigFieldType.StringArray + const {wrapper} = setup( + {fieldName, fieldType, value, isRequired: false}, + true + ) + + const input = wrapper.find(ArrayFormElement) + const formElement = wrapper.find(FormElement) expect(wrapper.exists()).toBe(true) expect(input.exists()).toBe(true) + expect(formElement.prop('helpText')).toBe('optional') }) }) + describe('if type is uri', () => { it('renders a uri input ', () => { const fieldName = ['http://google.com'] const fieldType = ConfigFieldType.Uri - const {wrapper} = setup({fieldName, fieldType}) + const value = '' + const {wrapper} = setup({fieldName, fieldType, value}, true) const input = wrapper.find(URIFormElement) expect(wrapper.exists()).toBe(true) expect(input.exists()).toBe(true) }) + + describe('if not required', () => { + it('optional is displayed as help text', () => { + const fieldName = ['http://google.com'] + const fieldType = ConfigFieldType.Uri + const value = '' + const {wrapper} = setup( + {fieldName, fieldType, value, isRequired: false}, + true + ) + + const input = wrapper.find(URIFormElement) + + expect(wrapper.exists()).toBe(true) + expect(input.exists()).toBe(true) + }) + }) }) }) diff --git a/ui/src/onboarding/components/configureStep/streaming/ConfigFieldSwitcher.tsx b/ui/src/onboarding/components/configureStep/streaming/ConfigFieldSwitcher.tsx index fddcd8f46d..3eb3b3c61f 100644 --- a/ui/src/onboarding/components/configureStep/streaming/ConfigFieldSwitcher.tsx +++ b/ui/src/onboarding/components/configureStep/streaming/ConfigFieldSwitcher.tsx @@ -18,6 +18,7 @@ interface Props { addTagValue: (item: string, fieldName: string) => void removeTagValue: (item: string, fieldName: string) => void value: string | string[] + isRequired: boolean } class ConfigFieldSwitcher extends PureComponent { @@ -33,6 +34,7 @@ class ConfigFieldSwitcher extends PureComponent { autoFocus={this.autoFocus} onChange={onChange} value={value as string} + helpText={this.optionalText} /> ) case ConfigFieldType.UriArray: @@ -44,11 +46,16 @@ class ConfigFieldSwitcher extends PureComponent { removeTagValue={this.props.removeTagValue} autoFocus={this.autoFocus} value={value as string[]} + helpText={this.optionalText} /> ) case ConfigFieldType.String: return ( - + { } } + private get optionalText(): string { + if (!this.props.isRequired) { + return 'optional' + } + } + private get autoFocus(): boolean { const {index} = this.props return index === 0 diff --git a/ui/src/onboarding/components/configureStep/streaming/PluginConfigForm.tsx b/ui/src/onboarding/components/configureStep/streaming/PluginConfigForm.tsx index 4b688a3035..807779d5e0 100644 --- a/ui/src/onboarding/components/configureStep/streaming/PluginConfigForm.tsx +++ b/ui/src/onboarding/components/configureStep/streaming/PluginConfigForm.tsx @@ -51,20 +51,23 @@ class PluginConfigForm extends PureComponent { return

No configuration required.

} - return Object.entries(configFields).map(([fieldName, fieldType], i) => { - return ( - - ) - }) + return Object.entries(configFields).map( + ([fieldName, {type: fieldType, isRequired}], i) => { + return ( + + ) + } + ) } private handleAddConfigFieldValue = ( diff --git a/ui/src/onboarding/constants/pluginConfigs.ts b/ui/src/onboarding/constants/pluginConfigs.ts index 48545be6f2..a69572f989 100644 --- a/ui/src/onboarding/constants/pluginConfigs.ts +++ b/ui/src/onboarding/constants/pluginConfigs.ts @@ -89,7 +89,12 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputDocker.NameEnum.Docker]: { - fields: {endpoint: ConfigFieldType.String}, + fields: { + endpoint: { + type: ConfigFieldType.String, + isRequired: true, + }, + }, defaults: { name: TelegrafPluginInputDocker.NameEnum.Docker, type: TelegrafPluginInputDocker.TypeEnum.Input, @@ -97,7 +102,12 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputFile.NameEnum.File]: { - fields: {files: ConfigFieldType.StringArray}, + fields: { + files: { + type: ConfigFieldType.StringArray, + isRequired: true, + }, + }, defaults: { name: TelegrafPluginInputFile.NameEnum.File, type: TelegrafPluginInputFile.TypeEnum.Input, @@ -113,7 +123,12 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputKubernetes.NameEnum.Kubernetes]: { - fields: {url: ConfigFieldType.Uri}, + fields: { + url: { + type: ConfigFieldType.Uri, + isRequired: true, + }, + }, defaults: { name: TelegrafPluginInputKubernetes.NameEnum.Kubernetes, type: TelegrafPluginInputKubernetes.TypeEnum.Input, @@ -121,7 +136,7 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputLogParser.NameEnum.Logparser]: { - fields: {files: ConfigFieldType.StringArray}, + fields: {files: {type: ConfigFieldType.StringArray, isRequired: true}}, defaults: { name: TelegrafPluginInputLogParser.NameEnum.Logparser, type: TelegrafPluginInputLogParser.TypeEnum.Input, @@ -169,7 +184,7 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputProcstat.NameEnum.Procstat]: { - fields: {exe: ConfigFieldType.String}, + fields: {exe: {type: ConfigFieldType.String, isRequired: false}}, defaults: { name: TelegrafPluginInputProcstat.NameEnum.Procstat, type: TelegrafPluginInputProcstat.TypeEnum.Input, @@ -177,7 +192,7 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputPrometheus.NameEnum.Prometheus]: { - fields: {urls: ConfigFieldType.UriArray}, + fields: {urls: {type: ConfigFieldType.UriArray, isRequired: true}}, defaults: { name: TelegrafPluginInputPrometheus.NameEnum.Prometheus, type: TelegrafPluginInputPrometheus.TypeEnum.Input, @@ -186,8 +201,8 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, [TelegrafPluginInputRedis.NameEnum.Redis]: { fields: { - servers: ConfigFieldType.StringArray, - password: ConfigFieldType.String, + servers: {type: ConfigFieldType.StringArray, isRequired: true}, + password: {type: ConfigFieldType.String, isRequired: false}, }, defaults: { name: TelegrafPluginInputRedis.NameEnum.Redis, @@ -196,7 +211,7 @@ export const telegrafPluginsInfo: TelegrafPluginInfo = { }, }, [TelegrafPluginInputSyslog.NameEnum.Syslog]: { - fields: {server: ConfigFieldType.String}, + fields: {server: {type: ConfigFieldType.String, isRequired: true}}, defaults: { name: TelegrafPluginInputSyslog.NameEnum.Syslog, type: TelegrafPluginInputSyslog.TypeEnum.Input, diff --git a/ui/src/onboarding/reducers/dataLoaders.ts b/ui/src/onboarding/reducers/dataLoaders.ts index c48eb9e4fb..0e804e0321 100644 --- a/ui/src/onboarding/reducers/dataLoaders.ts +++ b/ui/src/onboarding/reducers/dataLoaders.ts @@ -189,29 +189,36 @@ export default (state = INITIAL_STATE, action: Action): DataLoadersState => { return {...tp, configured: ConfigurationState.Configured} } - const plugin = getDeep(tp, 'plugin', createNewPlugin(name)) - const {config} = plugin + const {config} = getDeep( + tp, + 'plugin', + createNewPlugin(name) + ) + let isValidConfig = true - Object.entries(configFields).forEach(configField => { - const [fieldName, fieldType] = configField - const fieldValue = config[fieldName] + Object.entries(configFields).forEach( + ([fieldName, {type: fieldType, isRequired}]) => { + if (isRequired) { + const fieldValue = config[fieldName] - const isValidUri = - fieldType === ConfigFieldType.Uri && - validateURI(fieldValue as string) - const isValidString = - fieldType === ConfigFieldType.String && - (fieldValue as string) !== '' - const isValidArray = - (fieldType === ConfigFieldType.StringArray || - fieldType === ConfigFieldType.UriArray) && - (fieldValue as string[]).length + const isValidUri = + fieldType === ConfigFieldType.Uri && + validateURI(fieldValue as string) + const isValidString = + fieldType === ConfigFieldType.String && + (fieldValue as string) !== '' + const isValidArray = + (fieldType === ConfigFieldType.StringArray || + fieldType === ConfigFieldType.UriArray) && + (fieldValue as string[]).length - if (!isValidUri && !isValidString && !isValidArray) { - isValidConfig = false + if (!isValidUri && !isValidString && !isValidArray) { + isValidConfig = false + } + } } - }) + ) if (!isValidConfig || _.isEmpty(config)) { return {...tp, configured: ConfigurationState.Unconfigured} diff --git a/ui/src/shared/components/URIFormElement.test.tsx b/ui/src/shared/components/URIFormElement.test.tsx index 5aaf4b1771..53bf2d9204 100644 --- a/ui/src/shared/components/URIFormElement.test.tsx +++ b/ui/src/shared/components/URIFormElement.test.tsx @@ -11,6 +11,7 @@ const setup = (override = {}) => { name: '', value: '', onChange: jest.fn(), + helpText: '', ...override, } diff --git a/ui/src/shared/components/URIFormElement.tsx b/ui/src/shared/components/URIFormElement.tsx index eb365a055c..3b0ba3c788 100644 --- a/ui/src/shared/components/URIFormElement.tsx +++ b/ui/src/shared/components/URIFormElement.tsx @@ -14,6 +14,7 @@ interface Props { name: string autoFocus?: boolean value: string + helpText: string onChange: (e: ChangeEvent) => void } @@ -37,10 +38,15 @@ class URIFormElement extends PureComponent { } public render() { - const {name, value, autoFocus} = this.props + const {name, value, autoFocus, helpText} = this.props return ( - +