mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
refactor: Replace usages of Popover from react-bootstrap with Antd (#11163)
* New popover component * LimitControl * Moar components migrated * TimeSeriesColumnControl * Hotkeys * ColorPicker * FilterBoxItemCOntrol * AdhocFilterEditPopover * AdhocMetric * AnnotationLayerControl * DateFilterControl * Tests fix * Fix linting issue * Fix tests * Bug fix * Test fix * Remove Antd global stylesheet * Fix linting * Fix test * Fix test * Fix test * Fix test * Fix test
This commit is contained in:
committed by
GitHub
parent
4208ca76e0
commit
901a42b1df
@@ -26,7 +26,6 @@ import {
|
||||
SupersetClient,
|
||||
getCategoricalSchemeRegistry,
|
||||
getChartMetadataRegistry,
|
||||
ThemeProvider,
|
||||
validateNonEmpty,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
@@ -67,7 +66,6 @@ const propTypes = {
|
||||
timeColumn: PropTypes.string,
|
||||
intervalEndColumn: PropTypes.string,
|
||||
vizType: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
|
||||
error: PropTypes.string,
|
||||
colorScheme: PropTypes.string,
|
||||
@@ -666,7 +664,6 @@ export default class AnnotationLayer extends React.PureComponent {
|
||||
render() {
|
||||
const { isNew, name, annotationType, sourceType, show } = this.state;
|
||||
const isValid = this.isValidForm();
|
||||
const { theme } = this.props;
|
||||
const metadata = getChartMetadataRegistry().get(this.props.vizType);
|
||||
const supportedAnnotationTypes = metadata
|
||||
? metadata.supportedAnnotationTypes.map(
|
||||
@@ -676,7 +673,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
||||
const supportedSourceTypes = this.getSupportedSourceTypes(annotationType);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<>
|
||||
{this.props.error && (
|
||||
<span style={{ color: 'red' }}>ERROR: {this.props.error}</span>
|
||||
)}
|
||||
@@ -750,7 +747,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,11 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
OverlayTrigger,
|
||||
Popover,
|
||||
ListGroup,
|
||||
ListGroupItem,
|
||||
} from 'react-bootstrap';
|
||||
import { ListGroup, ListGroupItem } from 'react-bootstrap';
|
||||
import { connect } from 'react-redux';
|
||||
import { t, withTheme } from '@superset-ui/core';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import AsyncEsmComponent from 'src/components/AsyncEsmComponent';
|
||||
import { getChartKey } from 'src/explore/exploreUtils';
|
||||
import { runAnnotationQuery } from 'src/chart/chartAction';
|
||||
@@ -62,8 +58,10 @@ const defaultProps = {
|
||||
class AnnotationLayerControl extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { popoverVisible: false };
|
||||
this.addAnnotationLayer = this.addAnnotationLayer.bind(this);
|
||||
this.removeAnnotationLayer = this.removeAnnotationLayer.bind(this);
|
||||
this.handleVisibleChange = this.handleVisibleChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -101,6 +99,12 @@ class AnnotationLayerControl extends React.PureComponent {
|
||||
this.props.onChange(annotations);
|
||||
}
|
||||
|
||||
handleVisibleChange(visible, popoverKey) {
|
||||
this.setState(prevState => ({
|
||||
popoverVisible: { ...prevState, [popoverKey]: visible },
|
||||
}));
|
||||
}
|
||||
|
||||
removeAnnotationLayer(annotation) {
|
||||
const annotations = this.props.value
|
||||
.slice()
|
||||
@@ -108,18 +112,10 @@ class AnnotationLayerControl extends React.PureComponent {
|
||||
this.props.onChange(annotations);
|
||||
}
|
||||
|
||||
renderPopover(parent, annotation, error) {
|
||||
renderPopover(parent, popoverKey, annotation, error) {
|
||||
const id = !annotation ? '_new' : annotation.name;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<Popover
|
||||
data-test="annotation-popover"
|
||||
style={{ maxWidth: 'none' }}
|
||||
title={
|
||||
annotation ? t('Edit Annotation Layer') : t('Add Annotation Layer')
|
||||
}
|
||||
id={`annotation-pop-${id}`}
|
||||
>
|
||||
<div id={`annotation-pop-${id}`} data-test="popover-content">
|
||||
<AnnotationLayer
|
||||
{...annotation}
|
||||
parent={this.refs[parent]}
|
||||
@@ -128,10 +124,9 @@ class AnnotationLayerControl extends React.PureComponent {
|
||||
vizType={this.props.vizType}
|
||||
addAnnotationLayer={this.addAnnotationLayer}
|
||||
removeAnnotationLayer={this.removeAnnotationLayer}
|
||||
close={() => this.refs[parent].hide()}
|
||||
theme={theme}
|
||||
close={() => this.handleVisibleChange(false, popoverKey)}
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,34 +154,41 @@ class AnnotationLayerControl extends React.PureComponent {
|
||||
|
||||
render() {
|
||||
const annotations = this.props.value.map((anno, i) => (
|
||||
<OverlayTrigger
|
||||
<Popover
|
||||
key={i}
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref={`overlay-${i}`}
|
||||
placement="right"
|
||||
overlay={this.renderPopover(
|
||||
title={t('Edit Annotation Layer')}
|
||||
content={this.renderPopover(
|
||||
`overlay-${i}`,
|
||||
i,
|
||||
anno,
|
||||
this.props.annotationError[anno.name],
|
||||
)}
|
||||
visible={this.state.popoverVisible[i]}
|
||||
onVisibleChange={visible => this.handleVisibleChange(visible, i)}
|
||||
>
|
||||
<ListGroupItem>
|
||||
<span>{anno.name}</span>
|
||||
<span style={{ float: 'right' }}>{this.renderInfo(anno)}</span>
|
||||
</ListGroupItem>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
));
|
||||
|
||||
const addLayerPopoverKey = 'add';
|
||||
return (
|
||||
<div>
|
||||
<ListGroup>
|
||||
{annotations}
|
||||
<OverlayTrigger
|
||||
<Popover
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="overlay-new"
|
||||
placement="right"
|
||||
overlay={this.renderPopover('overlay-new')}
|
||||
content={this.renderPopover('overlay-new', addLayerPopoverKey)}
|
||||
title={t('Add Annotation Layer')}
|
||||
visible={this.state.popoverVisible[addLayerPopoverKey]}
|
||||
onVisibleChange={visible =>
|
||||
this.handleVisibleChange(visible, addLayerPopoverKey)
|
||||
}
|
||||
>
|
||||
<ListGroupItem>
|
||||
<i
|
||||
@@ -195,7 +197,7 @@ class AnnotationLayerControl extends React.PureComponent {
|
||||
/>{' '}
|
||||
{t('Add Annotation Layer')}
|
||||
</ListGroupItem>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</ListGroup>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import { SketchPicker } from 'react-color';
|
||||
import { getCategoricalSchemeRegistry } from '@superset-ui/core';
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import ControlHeader from '../ControlHeader';
|
||||
|
||||
const propTypes = {
|
||||
@@ -79,13 +79,13 @@ export default class ColorPickerControl extends React.Component {
|
||||
.get()
|
||||
.colors.filter((s, i) => i < 7);
|
||||
return (
|
||||
<Popover id="filter-popover" className="color-popover">
|
||||
<div id="filter-popover" className="color-popover">
|
||||
<SketchPicker
|
||||
color={this.props.value}
|
||||
onChange={this.onChange}
|
||||
presetColors={presetColors}
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,19 +98,16 @@ export default class ColorPickerControl extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<ControlHeader {...this.props} />
|
||||
<OverlayTrigger
|
||||
container={document.body}
|
||||
<Popover
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="trigger"
|
||||
placement="right"
|
||||
overlay={this.renderPopover()}
|
||||
content={this.renderPopover()}
|
||||
>
|
||||
<div style={styles.swatch}>
|
||||
<div style={styles.checkboard} />
|
||||
<div style={colStyle} />
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ import {
|
||||
InputGroup,
|
||||
MenuItem,
|
||||
OverlayTrigger,
|
||||
Popover,
|
||||
Radio,
|
||||
Tab,
|
||||
Tabs,
|
||||
Tooltip,
|
||||
} from 'react-bootstrap';
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import Button from 'src/components/Button';
|
||||
import Datetime from 'react-datetime';
|
||||
import 'react-datetime/css/react-datetime.css';
|
||||
@@ -206,6 +206,8 @@ class DateFilterControl extends React.Component {
|
||||
showUntilCalendar: false,
|
||||
sinceViewMode: 'days',
|
||||
untilViewMode: 'days',
|
||||
|
||||
popoverVisible: false,
|
||||
};
|
||||
|
||||
const { value } = props;
|
||||
@@ -230,6 +232,7 @@ class DateFilterControl extends React.Component {
|
||||
this.setTypeCustomStartEnd = this.setTypeCustomStartEnd.bind(this);
|
||||
this.toggleCalendar = this.toggleCalendar.bind(this);
|
||||
this.changeTab = this.changeTab.bind(this);
|
||||
this.handleVisibleChange = this.handleVisibleChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -328,8 +331,11 @@ class DateFilterControl extends React.Component {
|
||||
}
|
||||
this.props.onCloseDateFilterControl();
|
||||
this.props.onChange(val);
|
||||
this.refs.trigger.hide();
|
||||
this.setState({ showSinceCalendar: false, showUntilCalendar: false });
|
||||
this.setState({
|
||||
showSinceCalendar: false,
|
||||
showUntilCalendar: false,
|
||||
popoverVisible: false,
|
||||
});
|
||||
}
|
||||
|
||||
isValidSince(date) {
|
||||
@@ -362,6 +368,10 @@ class DateFilterControl extends React.Component {
|
||||
this.setState(nextState);
|
||||
}
|
||||
|
||||
handleVisibleChange(visible) {
|
||||
this.setState({ popoverVisible: visible });
|
||||
}
|
||||
|
||||
renderInput(props, key) {
|
||||
return (
|
||||
<FormGroup>
|
||||
@@ -374,7 +384,7 @@ class DateFilterControl extends React.Component {
|
||||
onClick={() => {}}
|
||||
/>
|
||||
<InputGroup.Button onClick={() => this.toggleCalendar(key)}>
|
||||
<Button theme={this.props.theme}>
|
||||
<Button>
|
||||
<i className="fa fa-calendar" />
|
||||
</Button>
|
||||
</InputGroup.Button>
|
||||
@@ -400,7 +410,7 @@ class DateFilterControl extends React.Component {
|
||||
const timeRange = buildTimeRangeString(nextState.since, nextState.until);
|
||||
|
||||
return (
|
||||
<Styles theme={this.props.theme} key={timeFrame}>
|
||||
<Styles key={timeFrame}>
|
||||
<OverlayTrigger
|
||||
key={timeFrame}
|
||||
placement="right"
|
||||
@@ -424,168 +434,166 @@ class DateFilterControl extends React.Component {
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Popover id="filter-popover" placement="top" positionTop={0}>
|
||||
<div
|
||||
style={DATE_FILTER_POPOVER_STYLE}
|
||||
ref={ref => {
|
||||
this.popoverContainer = ref;
|
||||
}}
|
||||
<div
|
||||
id="filter-popover"
|
||||
style={DATE_FILTER_POPOVER_STYLE}
|
||||
ref={ref => {
|
||||
this.popoverContainer = ref;
|
||||
}}
|
||||
>
|
||||
<Tabs
|
||||
defaultActiveKey={this.state.tab === TABS.DEFAULTS ? 1 : 2}
|
||||
id="type"
|
||||
className="time-filter-tabs"
|
||||
onSelect={this.changeTab}
|
||||
>
|
||||
<Tabs
|
||||
defaultActiveKey={this.state.tab === TABS.DEFAULTS ? 1 : 2}
|
||||
id="type"
|
||||
className="time-filter-tabs"
|
||||
onSelect={this.changeTab}
|
||||
>
|
||||
<Tab eventKey={1} title="Defaults">
|
||||
<FormGroup>{timeFrames}</FormGroup>
|
||||
</Tab>
|
||||
<Tab eventKey={2} title="Custom">
|
||||
<FormGroup>
|
||||
<PopoverSection
|
||||
title="Relative to today"
|
||||
isSelected={this.state.type === TYPES.CUSTOM_RANGE}
|
||||
onSelect={this.setTypeCustomRange}
|
||||
<Tab eventKey={1} title="Defaults">
|
||||
<FormGroup>{timeFrames}</FormGroup>
|
||||
</Tab>
|
||||
<Tab eventKey={2} title="Custom">
|
||||
<FormGroup>
|
||||
<PopoverSection
|
||||
title="Relative to today"
|
||||
isSelected={this.state.type === TYPES.CUSTOM_RANGE}
|
||||
onSelect={this.setTypeCustomRange}
|
||||
>
|
||||
<div
|
||||
className="clearfix centered"
|
||||
style={{ marginTop: '12px' }}
|
||||
>
|
||||
<div
|
||||
className="clearfix centered"
|
||||
style={{ marginTop: '12px' }}
|
||||
style={{ width: '60px', marginTop: '-4px' }}
|
||||
className="input-inline"
|
||||
>
|
||||
<div
|
||||
style={{ width: '60px', marginTop: '-4px' }}
|
||||
className="input-inline"
|
||||
<DropdownButton
|
||||
bsSize="small"
|
||||
componentClass={InputGroup.Button}
|
||||
id="input-dropdown-rel"
|
||||
title={this.state.rel}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
>
|
||||
<DropdownButton
|
||||
bsSize="small"
|
||||
componentClass={InputGroup.Button}
|
||||
id="input-dropdown-rel"
|
||||
title={this.state.rel}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
<MenuItem
|
||||
onSelect={value => this.setCustomRange('rel', value)}
|
||||
key={RELATIVE_TIME_OPTIONS.LAST}
|
||||
eventKey={RELATIVE_TIME_OPTIONS.LAST}
|
||||
active={this.state.rel === RELATIVE_TIME_OPTIONS.LAST}
|
||||
>
|
||||
<MenuItem
|
||||
onSelect={value => this.setCustomRange('rel', value)}
|
||||
key={RELATIVE_TIME_OPTIONS.LAST}
|
||||
eventKey={RELATIVE_TIME_OPTIONS.LAST}
|
||||
active={this.state.rel === RELATIVE_TIME_OPTIONS.LAST}
|
||||
>
|
||||
Last
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onSelect={value => this.setCustomRange('rel', value)}
|
||||
key={RELATIVE_TIME_OPTIONS.NEXT}
|
||||
eventKey={RELATIVE_TIME_OPTIONS.NEXT}
|
||||
active={this.state.rel === RELATIVE_TIME_OPTIONS.NEXT}
|
||||
>
|
||||
Next
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: '60px', marginTop: '-4px' }}
|
||||
className="input-inline m-l-5 m-r-3"
|
||||
Last
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onSelect={value => this.setCustomRange('rel', value)}
|
||||
key={RELATIVE_TIME_OPTIONS.NEXT}
|
||||
eventKey={RELATIVE_TIME_OPTIONS.NEXT}
|
||||
active={this.state.rel === RELATIVE_TIME_OPTIONS.NEXT}
|
||||
>
|
||||
Next
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: '60px', marginTop: '-4px' }}
|
||||
className="input-inline m-l-5 m-r-3"
|
||||
>
|
||||
<FormControl
|
||||
bsSize="small"
|
||||
type="text"
|
||||
onChange={event =>
|
||||
this.setCustomRange('num', event.target.value)
|
||||
}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
onKeyPress={this.onEnter}
|
||||
value={this.state.num}
|
||||
style={{ height: '30px' }}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: '90px', marginTop: '-4px' }}
|
||||
className="input-inline"
|
||||
>
|
||||
<DropdownButton
|
||||
bsSize="small"
|
||||
componentClass={InputGroup.Button}
|
||||
id="input-dropdown-grain"
|
||||
title={this.state.grain}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
>
|
||||
<FormControl
|
||||
bsSize="small"
|
||||
type="text"
|
||||
onChange={event =>
|
||||
this.setCustomRange('num', event.target.value)
|
||||
{grainOptions}
|
||||
</DropdownButton>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverSection>
|
||||
<PopoverSection
|
||||
title="Start / end"
|
||||
isSelected={this.state.type === TYPES.CUSTOM_START_END}
|
||||
onSelect={this.setTypeCustomStartEnd}
|
||||
info={FREEFORM_TOOLTIP}
|
||||
>
|
||||
<div
|
||||
ref={ref => {
|
||||
this.startEndSectionRef = ref;
|
||||
}}
|
||||
>
|
||||
<InputGroup data-test="date-input-group">
|
||||
<div style={{ margin: '5px 0' }}>
|
||||
<Datetime
|
||||
inputProps={{ 'data-test': 'date-from-input' }}
|
||||
value={this.state.since}
|
||||
defaultValue={this.state.since}
|
||||
viewDate={this.state.since}
|
||||
onChange={value =>
|
||||
this.setCustomStartEnd('since', value)
|
||||
}
|
||||
isValidDate={this.isValidSince}
|
||||
onClick={this.setTypeCustomStartEnd}
|
||||
renderInput={props =>
|
||||
this.renderInput(props, 'showSinceCalendar')
|
||||
}
|
||||
open={this.state.showSinceCalendar}
|
||||
viewMode={this.state.sinceViewMode}
|
||||
onViewModeChange={sinceViewMode =>
|
||||
this.setState({ sinceViewMode })
|
||||
}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
onKeyPress={this.onEnter}
|
||||
value={this.state.num}
|
||||
style={{ height: '30px' }}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: '90px', marginTop: '-4px' }}
|
||||
className="input-inline"
|
||||
>
|
||||
<DropdownButton
|
||||
bsSize="small"
|
||||
componentClass={InputGroup.Button}
|
||||
id="input-dropdown-grain"
|
||||
title={this.state.grain}
|
||||
onFocus={this.setTypeCustomRange}
|
||||
>
|
||||
{grainOptions}
|
||||
</DropdownButton>
|
||||
<div style={{ margin: '5px 0' }}>
|
||||
<Datetime
|
||||
inputProps={{ 'data-test': 'date-to-input' }}
|
||||
value={this.state.until}
|
||||
defaultValue={this.state.until}
|
||||
viewDate={this.state.until}
|
||||
onChange={value =>
|
||||
this.setCustomStartEnd('until', value)
|
||||
}
|
||||
isValidDate={this.isValidUntil}
|
||||
onClick={this.setTypeCustomStartEnd}
|
||||
renderInput={props =>
|
||||
this.renderInput(props, 'showUntilCalendar')
|
||||
}
|
||||
open={this.state.showUntilCalendar}
|
||||
viewMode={this.state.untilViewMode}
|
||||
onViewModeChange={untilViewMode =>
|
||||
this.setState({ untilViewMode })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverSection>
|
||||
<PopoverSection
|
||||
title="Start / end"
|
||||
isSelected={this.state.type === TYPES.CUSTOM_START_END}
|
||||
onSelect={this.setTypeCustomStartEnd}
|
||||
info={FREEFORM_TOOLTIP}
|
||||
>
|
||||
<div
|
||||
ref={ref => {
|
||||
this.startEndSectionRef = ref;
|
||||
}}
|
||||
>
|
||||
<InputGroup data-test="date-input-group">
|
||||
<div style={{ margin: '5px 0' }}>
|
||||
<Datetime
|
||||
inputProps={{ 'data-test': 'date-from-input' }}
|
||||
value={this.state.since}
|
||||
defaultValue={this.state.since}
|
||||
viewDate={this.state.since}
|
||||
onChange={value =>
|
||||
this.setCustomStartEnd('since', value)
|
||||
}
|
||||
isValidDate={this.isValidSince}
|
||||
onClick={this.setTypeCustomStartEnd}
|
||||
renderInput={props =>
|
||||
this.renderInput(props, 'showSinceCalendar')
|
||||
}
|
||||
open={this.state.showSinceCalendar}
|
||||
viewMode={this.state.sinceViewMode}
|
||||
onViewModeChange={sinceViewMode =>
|
||||
this.setState({ sinceViewMode })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ margin: '5px 0' }}>
|
||||
<Datetime
|
||||
inputProps={{ 'data-test': 'date-to-input' }}
|
||||
value={this.state.until}
|
||||
defaultValue={this.state.until}
|
||||
viewDate={this.state.until}
|
||||
onChange={value =>
|
||||
this.setCustomStartEnd('until', value)
|
||||
}
|
||||
isValidDate={this.isValidUntil}
|
||||
onClick={this.setTypeCustomStartEnd}
|
||||
renderInput={props =>
|
||||
this.renderInput(props, 'showUntilCalendar')
|
||||
}
|
||||
open={this.state.showUntilCalendar}
|
||||
viewMode={this.state.untilViewMode}
|
||||
onViewModeChange={untilViewMode =>
|
||||
this.setState({ untilViewMode })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</PopoverSection>
|
||||
</FormGroup>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div className="clearfix">
|
||||
<Button
|
||||
data-test="date-ok-button"
|
||||
buttonSize="small"
|
||||
className="float-right ok"
|
||||
buttonStyle="primary"
|
||||
onClick={this.close}
|
||||
theme={this.props.theme}
|
||||
>
|
||||
Ok
|
||||
</Button>
|
||||
</div>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</PopoverSection>
|
||||
</FormGroup>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div className="clearfix">
|
||||
<Button
|
||||
data-test="date-ok-button"
|
||||
buttonSize="small"
|
||||
className="float-right ok"
|
||||
buttonStyle="primary"
|
||||
onClick={this.close}
|
||||
>
|
||||
Ok
|
||||
</Button>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -594,15 +602,13 @@ class DateFilterControl extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<ControlHeader {...this.props} />
|
||||
<OverlayTrigger
|
||||
animation={this.props.animation}
|
||||
container={document.body}
|
||||
<Popover
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="trigger"
|
||||
placement="right"
|
||||
overlay={this.renderPopover()}
|
||||
content={this.renderPopover()}
|
||||
onClick={this.handleClickTrigger}
|
||||
visible={this.state.popoverVisible}
|
||||
onVisibleChange={this.handleVisibleChange}
|
||||
>
|
||||
<Label
|
||||
name="popover-trigger"
|
||||
@@ -611,7 +617,7 @@ class DateFilterControl extends React.Component {
|
||||
>
|
||||
{formatTimeRange(timeRange, this.props.endpoints)}
|
||||
</Label>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import FormRow from '../../../components/FormRow';
|
||||
import SelectControl from './SelectControl';
|
||||
import CheckboxControl from './CheckboxControl';
|
||||
@@ -81,7 +81,7 @@ export default class FilterBoxItemControl extends React.Component {
|
||||
label,
|
||||
defaultValue,
|
||||
} = props;
|
||||
const state = {
|
||||
this.state = {
|
||||
column,
|
||||
metric,
|
||||
label,
|
||||
@@ -91,7 +91,6 @@ export default class FilterBoxItemControl extends React.Component {
|
||||
searchAllOptions,
|
||||
defaultValue,
|
||||
};
|
||||
this.state = state;
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onControlChange = this.onControlChange.bind(this);
|
||||
}
|
||||
@@ -265,9 +264,9 @@ export default class FilterBoxItemControl extends React.Component {
|
||||
|
||||
renderPopover() {
|
||||
return (
|
||||
<Popover id="ts-col-popo" title={t('Filter Configuration')}>
|
||||
<div style={STYLE_WIDTH}>{this.renderForm()}</div>
|
||||
</Popover>
|
||||
<div id="ts-col-popo" style={STYLE_WIDTH}>
|
||||
{this.renderForm()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -275,20 +274,18 @@ export default class FilterBoxItemControl extends React.Component {
|
||||
return (
|
||||
<span>
|
||||
{this.textSummary()}{' '}
|
||||
<OverlayTrigger
|
||||
container={document.body}
|
||||
<Popover
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="trigger"
|
||||
placement="right"
|
||||
overlay={this.renderPopover()}
|
||||
content={this.renderPopover()}
|
||||
title={t('Filter Configuration')}
|
||||
>
|
||||
<InfoTooltipWithTrigger
|
||||
icon="edit"
|
||||
className="text-primary"
|
||||
label="edit-ts-column"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,8 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
FormControl,
|
||||
OverlayTrigger,
|
||||
Popover,
|
||||
} from 'react-bootstrap';
|
||||
import { Row, Col, FormControl } from 'react-bootstrap';
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import Select from 'src/components/Select';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
@@ -153,159 +148,157 @@ export default class TimeSeriesColumnControl extends React.Component {
|
||||
|
||||
renderPopover() {
|
||||
return (
|
||||
<Popover id="ts-col-popo" title="Column Configuration">
|
||||
<div style={{ width: 300 }}>
|
||||
{this.formRow(
|
||||
'Label',
|
||||
'The column header label',
|
||||
<div id="ts-col-popo" style={{ width: 300 }}>
|
||||
{this.formRow(
|
||||
'Label',
|
||||
'The column header label',
|
||||
'time-lag',
|
||||
<FormControl
|
||||
value={this.state.label}
|
||||
onChange={this.onTextInputChange.bind(this, 'label')}
|
||||
bsSize="small"
|
||||
placeholder="Label"
|
||||
/>,
|
||||
)}
|
||||
{this.formRow(
|
||||
'Tooltip',
|
||||
'Column header tooltip',
|
||||
'col-tooltip',
|
||||
<FormControl
|
||||
value={this.state.tooltip}
|
||||
onChange={this.onTextInputChange.bind(this, 'tooltip')}
|
||||
bsSize="small"
|
||||
placeholder="Tooltip"
|
||||
/>,
|
||||
)}
|
||||
{this.formRow(
|
||||
'Type',
|
||||
'Type of comparison, value difference or percentage',
|
||||
'col-type',
|
||||
<Select
|
||||
value={this.state.colType}
|
||||
clearable={false}
|
||||
onChange={this.onSelectChange.bind(this, 'colType')}
|
||||
options={colTypeOptions}
|
||||
/>,
|
||||
)}
|
||||
<hr />
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Width',
|
||||
'Width of the sparkline',
|
||||
'spark-width',
|
||||
<FormControl
|
||||
value={this.state.width}
|
||||
onChange={this.onTextInputChange.bind(this, 'width')}
|
||||
bsSize="small"
|
||||
placeholder="Width"
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Height',
|
||||
'Height of the sparkline',
|
||||
'spark-width',
|
||||
<FormControl
|
||||
value={this.state.height}
|
||||
onChange={this.onTextInputChange.bind(this, 'height')}
|
||||
bsSize="small"
|
||||
placeholder="height"
|
||||
/>,
|
||||
)}
|
||||
{['time', 'avg'].indexOf(this.state.colType) >= 0 &&
|
||||
this.formRow(
|
||||
'Time Lag',
|
||||
'Number of periods to compare against',
|
||||
'time-lag',
|
||||
<FormControl
|
||||
value={this.state.label}
|
||||
onChange={this.onTextInputChange.bind(this, 'label')}
|
||||
value={this.state.timeLag}
|
||||
onChange={this.onTextInputChange.bind(this, 'timeLag')}
|
||||
bsSize="small"
|
||||
placeholder="Label"
|
||||
placeholder="Time Lag"
|
||||
/>,
|
||||
)}
|
||||
{this.formRow(
|
||||
'Tooltip',
|
||||
'Column header tooltip',
|
||||
'col-tooltip',
|
||||
{['spark'].indexOf(this.state.colType) >= 0 &&
|
||||
this.formRow(
|
||||
'Time Ratio',
|
||||
'Number of periods to ratio against',
|
||||
'time-ratio',
|
||||
<FormControl
|
||||
value={this.state.tooltip}
|
||||
onChange={this.onTextInputChange.bind(this, 'tooltip')}
|
||||
value={this.state.timeRatio}
|
||||
onChange={this.onTextInputChange.bind(this, 'timeRatio')}
|
||||
bsSize="small"
|
||||
placeholder="Tooltip"
|
||||
placeholder="Time Ratio"
|
||||
/>,
|
||||
)}
|
||||
{this.formRow(
|
||||
{this.state.colType === 'time' &&
|
||||
this.formRow(
|
||||
'Type',
|
||||
'Type of comparison, value difference or percentage',
|
||||
'col-type',
|
||||
'comp-type',
|
||||
<Select
|
||||
value={this.state.colType}
|
||||
value={this.state.comparisonType}
|
||||
clearable={false}
|
||||
onChange={this.onSelectChange.bind(this, 'colType')}
|
||||
options={colTypeOptions}
|
||||
onChange={this.onSelectChange.bind(this, 'comparisonType')}
|
||||
options={comparisonTypeOptions}
|
||||
/>,
|
||||
)}
|
||||
<hr />
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Width',
|
||||
'Width of the sparkline',
|
||||
'spark-width',
|
||||
<FormControl
|
||||
value={this.state.width}
|
||||
onChange={this.onTextInputChange.bind(this, 'width')}
|
||||
bsSize="small"
|
||||
placeholder="Width"
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Height',
|
||||
'Height of the sparkline',
|
||||
'spark-width',
|
||||
<FormControl
|
||||
value={this.state.height}
|
||||
onChange={this.onTextInputChange.bind(this, 'height')}
|
||||
bsSize="small"
|
||||
placeholder="height"
|
||||
/>,
|
||||
)}
|
||||
{['time', 'avg'].indexOf(this.state.colType) >= 0 &&
|
||||
this.formRow(
|
||||
'Time Lag',
|
||||
'Number of periods to compare against',
|
||||
'time-lag',
|
||||
<FormControl
|
||||
value={this.state.timeLag}
|
||||
onChange={this.onTextInputChange.bind(this, 'timeLag')}
|
||||
bsSize="small"
|
||||
placeholder="Time Lag"
|
||||
/>,
|
||||
)}
|
||||
{['spark'].indexOf(this.state.colType) >= 0 &&
|
||||
this.formRow(
|
||||
'Time Ratio',
|
||||
'Number of periods to ratio against',
|
||||
'time-ratio',
|
||||
<FormControl
|
||||
value={this.state.timeRatio}
|
||||
onChange={this.onTextInputChange.bind(this, 'timeRatio')}
|
||||
bsSize="small"
|
||||
placeholder="Time Ratio"
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'time' &&
|
||||
this.formRow(
|
||||
'Type',
|
||||
'Type of comparison, value difference or percentage',
|
||||
'comp-type',
|
||||
<Select
|
||||
value={this.state.comparisonType}
|
||||
clearable={false}
|
||||
onChange={this.onSelectChange.bind(this, 'comparisonType')}
|
||||
options={comparisonTypeOptions}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Show Y-axis',
|
||||
'Show Y-axis on the sparkline. Will display the manually set min/max if set or min/max values in the data otherwise.',
|
||||
'show-y-axis-bounds',
|
||||
<CheckboxControl
|
||||
value={this.state.showYAxis}
|
||||
onChange={this.onCheckboxChange.bind(this, 'showYAxis')}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Y-axis bounds',
|
||||
'Manually set min/max values for the y-axis.',
|
||||
'y-axis-bounds',
|
||||
<BoundsControl
|
||||
value={this.state.yAxisBounds}
|
||||
onChange={this.onYAxisBoundsChange.bind(this)}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType !== 'spark' &&
|
||||
this.formRow(
|
||||
'Color bounds',
|
||||
`Number bounds used for color encoding from red to blue.
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Show Y-axis',
|
||||
'Show Y-axis on the sparkline. Will display the manually set min/max if set or min/max values in the data otherwise.',
|
||||
'show-y-axis-bounds',
|
||||
<CheckboxControl
|
||||
value={this.state.showYAxis}
|
||||
onChange={this.onCheckboxChange.bind(this, 'showYAxis')}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Y-axis bounds',
|
||||
'Manually set min/max values for the y-axis.',
|
||||
'y-axis-bounds',
|
||||
<BoundsControl
|
||||
value={this.state.yAxisBounds}
|
||||
onChange={this.onYAxisBoundsChange.bind(this)}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType !== 'spark' &&
|
||||
this.formRow(
|
||||
'Color bounds',
|
||||
`Number bounds used for color encoding from red to blue.
|
||||
Reverse the numbers for blue to red. To get pure red or blue,
|
||||
you can enter either only min or max.`,
|
||||
'bounds',
|
||||
<BoundsControl
|
||||
value={this.state.bounds}
|
||||
onChange={this.onBoundsChange.bind(this)}
|
||||
/>,
|
||||
)}
|
||||
{this.formRow(
|
||||
'Number format',
|
||||
'Optional d3 number format string',
|
||||
'd3-format',
|
||||
<FormControl
|
||||
value={this.state.d3format}
|
||||
onChange={this.onTextInputChange.bind(this, 'd3format')}
|
||||
bsSize="small"
|
||||
placeholder="Number format string"
|
||||
'bounds',
|
||||
<BoundsControl
|
||||
value={this.state.bounds}
|
||||
onChange={this.onBoundsChange.bind(this)}
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Date format',
|
||||
'Optional d3 date format string',
|
||||
'date-format',
|
||||
<FormControl
|
||||
value={this.state.dateFormat}
|
||||
onChange={this.onTextInputChange.bind(this, 'dateFormat')}
|
||||
bsSize="small"
|
||||
placeholder="Date format string"
|
||||
/>,
|
||||
)}
|
||||
</div>
|
||||
</Popover>
|
||||
{this.formRow(
|
||||
'Number format',
|
||||
'Optional d3 number format string',
|
||||
'd3-format',
|
||||
<FormControl
|
||||
value={this.state.d3format}
|
||||
onChange={this.onTextInputChange.bind(this, 'd3format')}
|
||||
bsSize="small"
|
||||
placeholder="Number format string"
|
||||
/>,
|
||||
)}
|
||||
{this.state.colType === 'spark' &&
|
||||
this.formRow(
|
||||
'Date format',
|
||||
'Optional d3 date format string',
|
||||
'date-format',
|
||||
<FormControl
|
||||
value={this.state.dateFormat}
|
||||
onChange={this.onTextInputChange.bind(this, 'dateFormat')}
|
||||
bsSize="small"
|
||||
placeholder="Date format string"
|
||||
/>,
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -313,13 +306,11 @@ export default class TimeSeriesColumnControl extends React.Component {
|
||||
return (
|
||||
<span>
|
||||
{this.textSummary()}{' '}
|
||||
<OverlayTrigger
|
||||
container={document.body}
|
||||
<Popover
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="trigger"
|
||||
placement="right"
|
||||
overlay={this.renderPopover()}
|
||||
content={this.renderPopover()}
|
||||
title="Column Configuration"
|
||||
>
|
||||
<InfoTooltipWithTrigger
|
||||
icon="edit"
|
||||
@@ -327,7 +318,7 @@ export default class TimeSeriesColumnControl extends React.Component {
|
||||
onClick={this.edit.bind(this)}
|
||||
label="edit-ts-column"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Popover, OverlayTrigger } from 'react-bootstrap';
|
||||
import Popover from 'src/common/components/Popover';
|
||||
import { decimal2sexagesimal } from 'geolib';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
@@ -83,9 +83,9 @@ export default class ViewportControl extends React.Component {
|
||||
|
||||
renderPopover() {
|
||||
return (
|
||||
<Popover id={`filter-popover-${this.props.name}`} title="Viewport">
|
||||
<div id={`filter-popover-${this.props.name}`}>
|
||||
{PARAMS.map(ctrl => this.renderTextControl(ctrl))}
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,16 +102,15 @@ export default class ViewportControl extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<ControlHeader {...this.props} />
|
||||
<OverlayTrigger
|
||||
<Popover
|
||||
container={document.body}
|
||||
trigger="click"
|
||||
rootClose
|
||||
ref="trigger"
|
||||
placement="right"
|
||||
overlay={this.renderPopover()}
|
||||
content={this.renderPopover()}
|
||||
title="Viewport"
|
||||
>
|
||||
<Label className="pointer">{this.renderLabel()}</Label>
|
||||
</OverlayTrigger>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user