From 331eb10fb953cf9730633ee734815578dab69d99 Mon Sep 17 00:00:00 2001
From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com>
Date: Thu, 13 May 2021 03:01:43 -0300
Subject: [PATCH] refactor: Bootstrap to AntD - Form - iteration 4 (#14546)
---
.../integration/explore/annotations.test.ts | 14 +-
.../explore/components/TextArea_spec.jsx | 8 +-
superset-frontend/src/CRUD/Field.jsx | 40 +++--
superset-frontend/src/CRUD/Fieldset.jsx | 4 +-
.../src/components/DeleteModal/index.tsx | 17 +-
.../src/datasource/ChangeDatasourceModal.tsx | 44 ++----
.../src/datasource/DatasourceEditor.jsx | 12 +-
.../components/PropertiesModal/index.tsx | 62 +++-----
...FilterEditPopoverSimpleTabContent.test.jsx | 3 +-
.../index.jsx | 145 +++++++++---------
...hocFilterEditPopoverSqlTabContent.test.jsx | 3 +-
.../index.jsx | 9 +-
.../components/controls/HiddenControl.jsx | 4 +-
.../AdhocMetricEditPopoverTitle.jsx | 4 +-
.../components/controls/TextAreaControl.jsx | 19 +--
.../components/controls/TextControl/index.tsx | 35 ++---
16 files changed, 188 insertions(+), 235 deletions(-)
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/annotations.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/annotations.test.ts
index a771ea5d2d..b895fa5847 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/annotations.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/annotations.test.ts
@@ -32,18 +32,8 @@ describe('Annotations', () => {
cy.get('[data-test=annotation_layers]').click();
cy.get('[data-test="popover-content"]').within(() => {
- cy.get('[data-test=annotation-layer-name-header]')
- .siblings()
- .first()
- .within(() => {
- cy.get('input').type(layerLabel);
- });
- cy.get('[data-test=annotation-layer-value-header]')
- .siblings()
- .first()
- .within(() => {
- cy.get('input').type('y=1400000');
- });
+ cy.get('[aria-label=Name]').type(layerLabel);
+ cy.get('[aria-label=Formula]').type('y=1400000');
cy.get('button').contains('OK').click();
});
diff --git a/superset-frontend/spec/javascripts/explore/components/TextArea_spec.jsx b/superset-frontend/spec/javascripts/explore/components/TextArea_spec.jsx
index 57c34b2455..fe804b5ec4 100644
--- a/superset-frontend/spec/javascripts/explore/components/TextArea_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/TextArea_spec.jsx
@@ -18,10 +18,10 @@
*/
/* eslint-disable no-unused-expressions */
import React from 'react';
-import { FormControl } from 'react-bootstrap';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import { TextAreaEditor } from 'src/components/AsyncAceEditor';
+import { TextArea } from 'src/common/components';
import TextAreaControl from 'src/explore/components/controls/TextAreaControl';
@@ -38,11 +38,11 @@ describe('SelectControl', () => {
});
it('renders a FormControl', () => {
- expect(wrapper.find(FormControl)).toExist();
+ expect(wrapper.find(TextArea)).toExist();
});
it('calls onChange when toggled', () => {
- const select = wrapper.find(FormControl);
+ const select = wrapper.find(TextArea);
select.simulate('change', { target: { value: 'x' } });
expect(defaultProps.onChange.calledWith('x')).toBe(true);
});
@@ -51,7 +51,7 @@ describe('SelectControl', () => {
const props = { ...defaultProps };
props.language = 'markdown';
wrapper = shallow();
- expect(wrapper.find(FormControl)).not.toExist();
+ expect(wrapper.find(TextArea)).not.toExist();
expect(wrapper.find(TextAreaEditor)).toExist();
});
});
diff --git a/superset-frontend/src/CRUD/Field.jsx b/superset-frontend/src/CRUD/Field.jsx
index 49f377d221..ca8c3f7082 100644
--- a/superset-frontend/src/CRUD/Field.jsx
+++ b/superset-frontend/src/CRUD/Field.jsx
@@ -18,10 +18,8 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { FormGroup, HelpBlock, FormControl } from 'react-bootstrap';
-
import { Tooltip } from 'src/components/Tooltip';
-import { FormLabel } from 'src/components/Form';
+import { FormItem, FormLabel } from 'src/components/Form';
import './crud.less';
const propTypes = {
@@ -63,19 +61,31 @@ export default class Field extends React.PureComponent {
onChange: this.onChange,
});
return (
-
-
- {label || fieldKey}
- {compact && description && (
-
-
-
- )}
- {' '}
+
+ {label || fieldKey}
+ {compact && description && (
+
+
+
+ )}
+
+ }
+ >
{hookedControl}
-
- {!compact && description && {description}}
-
+ {!compact && description && (
+
({
+ color: theme.colors.grayscale.base,
+ marginTop: theme.gridUnit,
+ })}
+ >
+ {description}
+
+ )}
+
);
}
}
diff --git a/superset-frontend/src/CRUD/Fieldset.jsx b/superset-frontend/src/CRUD/Fieldset.jsx
index dcbfc51308..3964af5c20 100644
--- a/superset-frontend/src/CRUD/Fieldset.jsx
+++ b/superset-frontend/src/CRUD/Fieldset.jsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Form } from 'react-bootstrap';
+import { Form } from 'src/components/Form';
import { recurseReactClone } from './utils';
import Field from './Field';
@@ -56,7 +56,7 @@ export default class Fieldset extends React.PureComponent {
compact: this.props.compact,
});
return (
-
diff --git a/superset-frontend/src/components/DeleteModal/index.tsx b/superset-frontend/src/components/DeleteModal/index.tsx
index e86d025e64..98639cddc0 100644
--- a/superset-frontend/src/components/DeleteModal/index.tsx
+++ b/superset-frontend/src/components/DeleteModal/index.tsx
@@ -18,11 +18,11 @@
*/
import { t, styled } from '@superset-ui/core';
import React, { useState } from 'react';
-import { FormGroup, FormControl, FormControlProps } from 'react-bootstrap';
+import { Input } from 'src/common/components';
import Modal from 'src/components/Modal';
import { FormLabel } from 'src/components/Form';
-const StyleFormGroup = styled(FormGroup)`
+const StyledDiv = styled.div`
padding-top: 8px;
width: 50%;
label {
@@ -64,24 +64,21 @@ export default function DeleteModal({
title={title}
>
{description}
-
+
{t('Type "%s" to confirm', t('DELETE'))}
- ,
- ) => {
- const targetValue = (event.currentTarget?.value as string) ?? '';
+ onChange={(event: React.ChangeEvent) => {
+ const targetValue = event.target.value ?? '';
setDisableChange(targetValue.toUpperCase() !== t('DELETE'));
}}
/>
-
+
);
}
diff --git a/superset-frontend/src/datasource/ChangeDatasourceModal.tsx b/superset-frontend/src/datasource/ChangeDatasourceModal.tsx
index c4a9bf7fa6..e33b8ed2aa 100644
--- a/superset-frontend/src/datasource/ChangeDatasourceModal.tsx
+++ b/superset-frontend/src/datasource/ChangeDatasourceModal.tsx
@@ -23,7 +23,6 @@ import React, {
useEffect,
useCallback,
} from 'react';
-import { FormControl, FormControlProps } from 'react-bootstrap';
import Alert from 'src/components/Alert';
import { SupersetClient, t, styled } from '@superset-ui/core';
import TableView, { EmptyWrapperType } from 'src/components/TableView';
@@ -32,9 +31,10 @@ import Button from 'src/components/Button';
import { useListViewResource } from 'src/views/CRUD/hooks';
import Dataset from 'src/types/Dataset';
import { useDebouncedEffect } from 'src/explore/exploreUtils';
-import { getClientErrorObject } from '../utils/getClientErrorObject';
-import Loading from '../components/Loading';
-import withToasts from '../messageToasts/enhancers/withToasts';
+import { getClientErrorObject } from 'src/utils/getClientErrorObject';
+import Loading from 'src/components/Loading';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
+import { Input, AntdInput } from 'src/common/components';
const CONFIRM_WARNING_MESSAGE = t(
'Warning! Changing the dataset may break the chart if the metadata does not exist.',
@@ -107,7 +107,7 @@ const ChangeDatasourceModal: FunctionComponent = ({
const [filter, setFilter] = useState(undefined);
const [confirmChange, setConfirmChange] = useState(false);
const [confirmedDataset, setConfirmedDataset] = useState();
- let searchRef = useRef(null);
+ const searchRef = useRef(null);
const {
state: { loading, resourceCollection },
@@ -140,9 +140,7 @@ const ChangeDatasourceModal: FunctionComponent = ({
useEffect(() => {
const onEnterModal = async () => {
- if (searchRef && searchRef.current) {
- searchRef.current.focus();
- }
+ setTimeout(() => searchRef?.current?.focus(), 200);
};
if (show) {
@@ -158,14 +156,8 @@ const ChangeDatasourceModal: FunctionComponent = ({
show,
]);
- const setSearchRef = (ref: any) => {
- searchRef = ref;
- };
-
- const changeSearch = (
- event: React.FormEvent,
- ) => {
- const searchValue = (event.currentTarget?.value as string) ?? '';
+ const changeSearch = (event: React.ChangeEvent) => {
+ const searchValue = event.target.value ?? '';
setFilter(searchValue);
};
@@ -250,24 +242,20 @@ const ChangeDatasourceModal: FunctionComponent = ({
({ marginBottom: theme.gridUnit * 4 })}
message={
<>
{t('Warning!')} {CHANGE_WARNING_MSG}
>
}
/>
-
- {
- setSearchRef(ref);
- }}
- type="text"
- bsSize="sm"
- value={filter}
- placeholder={t('Search / Filter')}
- onChange={changeSearch}
- />
-
+
{loading && }
{!loading && (
)}
{this.state.datasourceType === DATASOURCE_TYPES.physical.key && (
-
+
{this.state.isSqla && (
-
-
+
+
{this.renderSettingsFieldset()}
-
+
{this.renderAdvancedFieldset()}
-
+
diff --git a/superset-frontend/src/explore/components/PropertiesModal/index.tsx b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
index bab4971b53..0c46f6ba79 100644
--- a/superset-frontend/src/explore/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
@@ -18,15 +18,14 @@
*/
import React, { useState, useEffect, useCallback } from 'react';
import Modal from 'src/components/Modal';
-import { Row, Col } from 'src/common/components';
-import { FormControl, FormGroup, FormControlProps } from 'react-bootstrap';
+import { Row, Col, Input, TextArea } from 'src/common/components';
import Button from 'src/components/Button';
import { OptionsType } from 'react-select/src/types';
import { AsyncSelect } from 'src/components/Select';
import rison from 'rison';
import { t, SupersetClient } from '@superset-ui/core';
import Chart, { Slice } from 'src/types/Chart';
-import { FormLabel } from 'src/components/Form';
+import { Form, FormItem } from 'src/components/Form';
import { getClientErrorObject } from 'src/utils/getClientErrorObject';
type PropertiesModalProps = {
@@ -186,37 +185,28 @@ export default function PropertiesModal({
responsive
wrapProps={{ 'data-test': 'properties-edit-modal' }}
>
-
+
);
}
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.jsx
index 8c57c78dc5..7eb5036eae 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.jsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.jsx
@@ -20,7 +20,6 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import { FormGroup } from 'react-bootstrap';
import AdhocFilter, {
EXPRESSION_TYPES,
@@ -86,7 +85,7 @@ function setup(overrides) {
describe('AdhocFilterEditPopoverSimpleTabContent', () => {
it('renders the simple tab form', () => {
const { wrapper } = setup();
- expect(wrapper.find(FormGroup)).toHaveLength(3);
+ expect(wrapper).toExist();
});
it('passes the new adhocFilter to onChange after onSubjectChange', () => {
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.jsx
index 391bb74c8a..e1b4aad3b1 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.jsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.jsx
@@ -18,7 +18,6 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { FormGroup } from 'react-bootstrap';
import { NativeSelect as Select } from 'src/components/Select';
import { Input } from 'src/common/components';
import { t, SupersetClient, styled } from '@superset-ui/core';
@@ -346,80 +345,80 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
return (
<>
-
-
-
-
-
-
-
- {MULTI_OPERATORS.has(operator) ||
- this.state.suggestions.length > 0 ? (
- triggerNode.parentNode}
- onSearch={val => this.setState({ currentSuggestionSearch: val })}
- onSelect={this.clearSuggestionSearch}
- onBlur={this.clearSuggestionSearch}
+
+
+ {MULTI_OPERATORS.has(operator) || this.state.suggestions.length > 0 ? (
+ triggerNode.parentNode}
+ onSearch={val => this.setState({ currentSuggestionSearch: val })}
+ onSelect={this.clearSuggestionSearch}
+ onBlur={this.clearSuggestionSearch}
+ >
+ {this.state.suggestions.map(suggestion => (
+
+ {suggestion}
+
+ ))}
- {/* enable selecting an option not included in suggestions */}
- {currentSuggestionSearch &&
- !this.state.suggestions.some(
- suggestion => suggestion === currentSuggestionSearch,
- ) && (
-
- {currentSuggestionSearch}
-
- )}
-
- ) : (
- this.focusComparator(ref, focusComparator)}
- onChange={this.onInputComparatorChange}
- value={comparator}
- placeholder={t('Filter value (case sensitive)')}
- disabled={DISABLE_INPUT_OPERATORS.includes(operator)}
- />
- )}
-
+ {/* enable selecting an option not included in suggestions */}
+ {currentSuggestionSearch &&
+ !this.state.suggestions.some(
+ suggestion => suggestion === currentSuggestionSearch,
+ ) && (
+
+ {currentSuggestionSearch}
+
+ )}
+
+ ) : (
+ this.focusComparator(ref, focusComparator)}
+ onChange={this.onInputComparatorChange}
+ value={comparator}
+ placeholder={t('Filter value (case sensitive)')}
+ disabled={DISABLE_INPUT_OPERATORS.includes(operator)}
+ />
+ )}
>
);
}
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/AdhocFilterEditPopoverSqlTabContent.test.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/AdhocFilterEditPopoverSqlTabContent.test.jsx
index 09b0d4ea48..00969225f6 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/AdhocFilterEditPopoverSqlTabContent.test.jsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/AdhocFilterEditPopoverSqlTabContent.test.jsx
@@ -20,7 +20,6 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import { FormGroup } from 'react-bootstrap';
import AdhocFilter, {
EXPRESSION_TYPES,
@@ -50,7 +49,7 @@ function setup(overrides) {
describe('AdhocFilterEditPopoverSqlTabContent', () => {
it('renders the sql tab form', () => {
const { wrapper } = setup();
- expect(wrapper.find(FormGroup)).toHaveLength(2);
+ expect(wrapper).toExist();
});
it('passes the new clause to onChange after onSqlExpressionClauseChange', () => {
diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx
index 405d692a94..688302f487 100644
--- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx
+++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx
@@ -18,7 +18,6 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { FormGroup } from 'react-bootstrap';
import { NativeSelect as Select } from 'src/components/Select';
import { t } from '@superset-ui/core';
import { SQLEditor } from 'src/components/AsyncAceEditor';
@@ -115,7 +114,7 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
return (
-
+
HAVING {t('Filters by metrics')}
-
-
+
+ ({ marginTop: theme.gridUnit * 4 })}>
-
+
);
}
diff --git a/superset-frontend/src/explore/components/controls/HiddenControl.jsx b/superset-frontend/src/explore/components/controls/HiddenControl.jsx
index a6287a056a..bc656af856 100644
--- a/superset-frontend/src/explore/components/controls/HiddenControl.jsx
+++ b/superset-frontend/src/explore/components/controls/HiddenControl.jsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { FormControl } from 'react-bootstrap';
+import { Input } from 'src/common/components';
const propTypes = {
onChange: PropTypes.func,
@@ -38,7 +38,7 @@ const defaultProps = {
export default function HiddenControl(props) {
// This wouldn't be necessary but might as well
- return ;
+ return ;
}
HiddenControl.propTypes = propTypes;
diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle.jsx b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle.jsx
index ea1e401046..4e9e7c011c 100644
--- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle.jsx
+++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle.jsx
@@ -19,7 +19,7 @@
import React from 'react';
import { t } from '@superset-ui/core';
import PropTypes from 'prop-types';
-import { FormControl } from 'react-bootstrap';
+import { Input } from 'src/common/components';
import { Tooltip } from 'src/components/Tooltip';
const propTypes = {
@@ -79,7 +79,7 @@ export default class AdhocMetricEditPopoverTitle extends React.Component {
}
return this.state.isEditMode ? (
-
-
-
+
);
}
diff --git a/superset-frontend/src/explore/components/controls/TextControl/index.tsx b/superset-frontend/src/explore/components/controls/TextControl/index.tsx
index ee41cbdf02..b3d99b973d 100644
--- a/superset-frontend/src/explore/components/controls/TextControl/index.tsx
+++ b/superset-frontend/src/explore/components/controls/TextControl/index.tsx
@@ -17,11 +17,11 @@
* under the License.
*/
import React from 'react';
-import { FormGroup, FormControl, FormControlProps } from 'react-bootstrap';
import { legacyValidateNumber, legacyValidateInteger } from '@superset-ui/core';
import debounce from 'lodash/debounce';
import { FAST_DEBOUNCE } from 'src/constants';
import ControlHeader from 'src/explore/components/ControlHeader';
+import { Input } from 'src/common/components';
type InputValueType = string | number;
@@ -39,13 +39,9 @@ export interface TextControlProps {
}
export interface TextControlState {
- controlId: string;
value: string;
}
-const generateControlId = (controlId?: string) =>
- `formInlineName_${controlId ?? (Math.random() * 1000000).toFixed()}`;
-
const safeStringify = (value?: InputValueType | null) =>
value == null ? '' : String(value);
@@ -58,9 +54,6 @@ export default class TextControl<
super(props);
this.initialValue = props.value;
this.state = {
- // if there's no control id provided, generate a random
- // number to prevent rendering elements with same ids
- controlId: generateControlId(props.controlId),
value: safeStringify(this.initialValue),
};
}
@@ -94,8 +87,8 @@ export default class TextControl<
this.onChange(inputValue);
}, FAST_DEBOUNCE);
- onChangeWrapper: FormControlProps['onChange'] = event => {
- const { value } = event.target as HTMLInputElement;
+ onChangeWrapper = (event: React.ChangeEvent) => {
+ const { value } = event.target;
this.setState({ value }, () => {
this.debouncedOnChange(value);
});
@@ -110,18 +103,16 @@ export default class TextControl<
return (
-
-
-
+
);
};