You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by cw...@apache.org on 2021/05/13 05:24:15 UTC
[druid] branch 0.21.1 updated: Fix required field treatment
(#11228) (#11237)
This is an automated email from the ASF dual-hosted git repository.
cwylie pushed a commit to branch 0.21.1
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/0.21.1 by this push:
new 5d6f141 Fix required field treatment (#11228) (#11237)
5d6f141 is described below
commit 5d6f141d71ca74a3eb2e0f02ce01bfba1e53b2f0
Author: Clint Wylie <cw...@apache.org>
AuthorDate: Wed May 12 22:23:27 2021 -0700
Fix required field treatment (#11228) (#11237)
Co-authored-by: Vadim Ogievetsky <va...@ogievetsky.com>
---
.../__snapshots__/auto-form.spec.tsx.snap | 66 +++++++++++++++------
.../src/components/auto-form/auto-form.spec.tsx | 28 ++++++---
web-console/src/components/auto-form/auto-form.tsx | 69 +++++++++++-----------
web-console/src/druid-models/ingestion-spec.tsx | 1 -
web-console/src/druid-models/timestamp-spec.tsx | 1 -
.../src/views/load-data-view/load-data-view.tsx | 15 +++--
6 files changed, 113 insertions(+), 67 deletions(-)
diff --git a/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
index 02a63a1..0e28a10 100644
--- a/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
+++ b/web-console/src/components/auto-form/__snapshots__/auto-form.spec.tsx.snap
@@ -5,8 +5,8 @@ exports[`AutoForm matches snapshot 1`] = `
className="auto-form"
>
<Memo(FormGroupWithInfo)
- key="testOne"
- label="Test one"
+ key="testNumber"
+ label="Test number"
>
<Memo(NumericInputWithDefault)
disabled={false}
@@ -18,8 +18,8 @@ exports[`AutoForm matches snapshot 1`] = `
/>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testTwo"
- label="Test two"
+ key="testSizeBytes"
+ label="Test size bytes"
>
<Blueprint3.NumericInput
allowNumericCharactersOnly={true}
@@ -40,8 +40,8 @@ exports[`AutoForm matches snapshot 1`] = `
/>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testThree"
- label="Test three"
+ key="testString"
+ label="Test string"
>
<Memo(SuggestibleInput)
disabled={false}
@@ -52,8 +52,20 @@ exports[`AutoForm matches snapshot 1`] = `
/>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testFour"
- label="Test four"
+ key="testStringWithDefault"
+ label="Test string with default"
+ >
+ <Memo(SuggestibleInput)
+ disabled={false}
+ onBlur={[Function]}
+ onValueChange={[Function]}
+ placeholder=""
+ value="Hello World"
+ />
+ </Memo(FormGroupWithInfo)>
+ <Memo(FormGroupWithInfo)
+ key="testBoolean"
+ label="Test boolean"
>
<Blueprint3.ButtonGroup>
<Blueprint3.Button
@@ -73,8 +85,8 @@ exports[`AutoForm matches snapshot 1`] = `
</Blueprint3.ButtonGroup>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testFourWithDefault"
- label="Test four with default"
+ key="testBooleanWithDefault"
+ label="Test boolean with default"
>
<Blueprint3.ButtonGroup>
<Blueprint3.Button
@@ -94,8 +106,8 @@ exports[`AutoForm matches snapshot 1`] = `
</Blueprint3.ButtonGroup>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testFive"
- label="Test five"
+ key="testStringArray"
+ label="Test string array"
>
<Memo(ArrayInput)
disabled={false}
@@ -105,23 +117,43 @@ exports[`AutoForm matches snapshot 1`] = `
/>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testSix"
- label="Test six"
+ key="testStringArrayWithDefault"
+ label="Test string array with default"
>
- <Memo(JsonInput)
+ <Memo(ArrayInput)
+ disabled={false}
onChange={[Function]}
placeholder=""
+ values={
+ Array [
+ "Hello",
+ "World",
+ ]
+ }
/>
</Memo(FormGroupWithInfo)>
<Memo(FormGroupWithInfo)
- key="testSeven"
- label="Test seven"
+ key="testJson"
+ label="Test json"
>
<Memo(JsonInput)
onChange={[Function]}
placeholder=""
/>
</Memo(FormGroupWithInfo)>
+ <Memo(FormGroupWithInfo)
+ key="testStringRequiredAndDefaultValue"
+ label="Test string required and default value"
+ >
+ <Memo(SuggestibleInput)
+ disabled={false}
+ intent="primary"
+ onBlur={[Function]}
+ onValueChange={[Function]}
+ placeholder=""
+ value=""
+ />
+ </Memo(FormGroupWithInfo)>
<Blueprint3.FormGroup
key="more-or-less"
>
diff --git a/web-console/src/components/auto-form/auto-form.spec.tsx b/web-console/src/components/auto-form/auto-form.spec.tsx
index d0e6c41..c239130 100644
--- a/web-console/src/components/auto-form/auto-form.spec.tsx
+++ b/web-console/src/components/auto-form/auto-form.spec.tsx
@@ -28,14 +28,26 @@ describe('AutoForm', () => {
const autoForm = shallow(
<AutoForm
fields={[
- { name: 'testOne', type: 'number' },
- { name: 'testTwo', type: 'size-bytes' },
- { name: 'testThree', type: 'string' },
- { name: 'testFour', type: 'boolean' },
- { name: 'testFourWithDefault', type: 'boolean', defaultValue: false },
- { name: 'testFive', type: 'string-array' },
- { name: 'testSix', type: 'json' },
- { name: 'testSeven', type: 'json' },
+ { name: 'testNumber', type: 'number' },
+ { name: 'testSizeBytes', type: 'size-bytes' },
+ { name: 'testString', type: 'string' },
+ { name: 'testStringWithDefault', type: 'string', defaultValue: 'Hello World' },
+ { name: 'testBoolean', type: 'boolean' },
+ { name: 'testBooleanWithDefault', type: 'boolean', defaultValue: false },
+ { name: 'testStringArray', type: 'string-array' },
+ {
+ name: 'testStringArrayWithDefault',
+ type: 'string-array',
+ defaultValue: ['Hello', 'World'],
+ },
+ { name: 'testJson', type: 'json' },
+
+ {
+ name: 'testStringRequiredAndDefaultValue',
+ type: 'string',
+ defaultValue: 'hello',
+ required: () => true,
+ },
{ name: 'testNotDefined', type: 'string', defined: false },
{ name: 'testAdvanced', type: 'string', hideInMore: true },
diff --git a/web-console/src/components/auto-form/auto-form.tsx b/web-console/src/components/auto-form/auto-form.tsx
index 32dc874..86c44b8 100644
--- a/web-console/src/components/auto-form/auto-form.tsx
+++ b/web-console/src/components/auto-form/auto-form.tsx
@@ -62,6 +62,12 @@ export interface Field<M> {
issueWithValue?: (value: any) => string | undefined;
}
+interface ComputedFieldValues {
+ required: boolean;
+ defaultValue?: any;
+ modelValue: any;
+}
+
export interface AutoFormProps<M> {
fields: Field<M>[];
model: M | undefined;
@@ -93,6 +99,15 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
return newLabel;
}
+ static computeFieldValues<M>(model: M | undefined, field: Field<M>): ComputedFieldValues {
+ const required = AutoForm.evaluateFunctor(field.required, model, false);
+ return {
+ required,
+ defaultValue: required ? undefined : field.defaultValue,
+ modelValue: deepGet(model as any, field.name),
+ };
+ }
+
static evaluateFunctor<M, R>(
functor: undefined | Functor<M, R>,
model: M | undefined,
@@ -204,12 +219,12 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
private renderNumberInput(field: Field<T>): JSX.Element {
const { model, large, onFinalize } = this.props;
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
- const modelValue = deepGet(model as any, field.name);
return (
<NumericInputWithDefault
value={modelValue}
- defaultValue={field.defaultValue}
+ defaultValue={defaultValue}
onValueChange={(valueAsNumber: number, valueAsString: string) => {
let newValue: number | undefined;
if (valueAsString !== '' && !isNaN(valueAsNumber)) {
@@ -228,21 +243,18 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
large={large}
disabled={AutoForm.evaluateFunctor(field.disabled, model, false)}
placeholder={AutoForm.evaluateFunctor(field.placeholder, model, '')}
- intent={
- AutoForm.evaluateFunctor(field.required, model, false) && modelValue == null
- ? AutoForm.REQUIRED_INTENT
- : undefined
- }
+ intent={required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined}
/>
);
}
private renderSizeBytesInput(field: Field<T>): JSX.Element {
const { model, large, onFinalize } = this.props;
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
return (
<NumericInput
- value={deepGet(model as any, field.name) || field.defaultValue}
+ value={modelValue || defaultValue}
onValueChange={(v: number) => {
if (isNaN(v)) return;
this.fieldChange(field, v);
@@ -256,17 +268,18 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
fill
large={large}
disabled={AutoForm.evaluateFunctor(field.disabled, model, false)}
+ intent={required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined}
/>
);
}
private renderStringInput(field: Field<T>, sanitize?: (str: string) => string): JSX.Element {
const { model, large, onFinalize } = this.props;
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
- const modelValue = deepGet(model as any, field.name);
return (
<SuggestibleInput
- value={modelValue != null ? modelValue : field.defaultValue || ''}
+ value={modelValue != null ? modelValue : defaultValue || ''}
onValueChange={v => {
if (sanitize && typeof v === 'string') v = sanitize(v);
this.fieldChange(field, v);
@@ -279,24 +292,17 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
suggestions={AutoForm.evaluateFunctor(field.suggestions, model, undefined)}
large={large}
disabled={AutoForm.evaluateFunctor(field.disabled, model, false)}
- intent={
- AutoForm.evaluateFunctor(field.required, model, false) && modelValue == null
- ? AutoForm.REQUIRED_INTENT
- : undefined
- }
+ intent={required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined}
/>
);
}
private renderBooleanInput(field: Field<T>): JSX.Element {
const { model, large, onFinalize } = this.props;
- const modelValue = deepGet(model as any, field.name);
- const shownValue = modelValue == null ? field.defaultValue : modelValue;
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
+ const shownValue = modelValue == null ? defaultValue : modelValue;
const disabled = AutoForm.evaluateFunctor(field.disabled, model, false);
- const intent =
- AutoForm.evaluateFunctor(field.required, model, false) && modelValue == null
- ? AutoForm.REQUIRED_INTENT
- : undefined;
+ const intent = required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined;
return (
<ButtonGroup large={large}>
@@ -342,41 +348,34 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
private renderStringArrayInput(field: Field<T>): JSX.Element {
const { model, large } = this.props;
- const modelValue = deepGet(model as any, field.name);
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
+
return (
<ArrayInput
- values={modelValue || []}
+ values={modelValue || defaultValue || []}
onChange={(v: any) => {
this.fieldChange(field, v);
}}
placeholder={AutoForm.evaluateFunctor(field.placeholder, model, '')}
large={large}
disabled={AutoForm.evaluateFunctor(field.disabled, model, false)}
- intent={
- AutoForm.evaluateFunctor(field.required, model, false) && modelValue == null
- ? AutoForm.REQUIRED_INTENT
- : undefined
- }
+ intent={required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined}
/>
);
}
private renderIntervalInput(field: Field<T>): JSX.Element {
const { model } = this.props;
+ const { required, defaultValue, modelValue } = AutoForm.computeFieldValues(model, field);
- const modelValue = deepGet(model as any, field.name);
return (
<IntervalInput
- interval={modelValue != null ? modelValue : field.defaultValue || ''}
+ interval={modelValue != null ? modelValue : defaultValue || ''}
onValueChange={(v: any) => {
this.fieldChange(field, v);
}}
placeholder={AutoForm.evaluateFunctor(field.placeholder, model, '')}
- intent={
- AutoForm.evaluateFunctor(field.required, model, false) && modelValue == null
- ? AutoForm.REQUIRED_INTENT
- : undefined
- }
+ intent={required && modelValue == null ? AutoForm.REQUIRED_INTENT : undefined}
/>
);
}
diff --git a/web-console/src/druid-models/ingestion-spec.tsx b/web-console/src/druid-models/ingestion-spec.tsx
index d4c9bdc..b963f31 100644
--- a/web-console/src/druid-models/ingestion-spec.tsx
+++ b/web-console/src/druid-models/ingestion-spec.tsx
@@ -908,7 +908,6 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
'kinesis.us-gov-east-1.amazonaws.com',
'kinesis.us-gov-west-1.amazonaws.com',
],
- required: true,
info: (
<>
The Amazon Kinesis stream endpoint for a region. You can find a list of endpoints{' '}
diff --git a/web-console/src/druid-models/timestamp-spec.tsx b/web-console/src/druid-models/timestamp-spec.tsx
index b6c595b..01fcfd3 100644
--- a/web-console/src/druid-models/timestamp-spec.tsx
+++ b/web-console/src/druid-models/timestamp-spec.tsx
@@ -100,7 +100,6 @@ export const TIMESTAMP_SPEC_FIELDS: Field<TimestampSpec>[] = [
name: 'column',
type: 'string',
defaultValue: 'timestamp',
- required: true,
},
{
name: 'format',
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index 783b448..daf79a3 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -706,7 +706,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
comboType: IngestionComboTypeWithExtra,
disabled?: boolean,
): JSX.Element | undefined {
- const { overlordModules, selectedComboType } = this.state;
+ const { overlordModules, selectedComboType, spec } = this.state;
if (!overlordModules) return;
const requiredModule = getRequiredModule(comboType);
const goodToGo = !disabled && (!requiredModule || overlordModules.includes(requiredModule));
@@ -716,10 +716,15 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
className={classNames({ disabled: !goodToGo, active: selectedComboType === comboType })}
interactive
elevation={1}
- onClick={() => {
- this.setState({
- selectedComboType: selectedComboType !== comboType ? comboType : undefined,
- });
+ onClick={e => {
+ if (e.altKey && e.shiftKey) {
+ this.updateSpec(updateIngestionType(spec, comboType as any));
+ this.updateStep('connect');
+ } else {
+ this.setState({
+ selectedComboType: selectedComboType !== comboType ? comboType : undefined,
+ });
+ }
}}
>
<img
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org