feat: Custom filters control (#17006)

* fix:fix get permission function

* feat: customize filter control

* fix: fix types

* fix: fix merge

* refactor: update according CR

* refactor: fix CR notes
This commit is contained in:
simcha90 2021-10-15 14:14:04 +03:00 committed by GitHub
parent 69604c316f
commit eebc953dd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 67 deletions

View File

@ -59,6 +59,8 @@ const selectedMetricType = PropTypes.oneOfType([
const propTypes = {
label: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
name: PropTypes.string,
sections: PropTypes.arrayOf(PropTypes.string),
operators: PropTypes.arrayOf(PropTypes.string),
onChange: PropTypes.func,
value: PropTypes.arrayOf(adhocFilterType),
datasource: PropTypes.object,
@ -107,6 +109,8 @@ class AdhocFilterControl extends React.Component {
adhocFilter={adhocFilter}
onFilterEdit={this.onFilterEdit}
options={this.state.options}
sections={this.props.sections}
operators={this.props.operators}
datasource={this.props.datasource}
onRemoveFilter={() => this.onRemoveFilter(index)}
onMoveLabel={this.moveLabel}
@ -324,6 +328,8 @@ class AdhocFilterControl extends React.Component {
addNewFilterPopoverTrigger(trigger) {
return (
<AdhocFilterPopoverTrigger
operators={this.props.operators}
sections={this.props.sections}
adhocFilter={new AdhocFilter({})}
datasource={this.props.datasource}
options={this.state.options}

View File

@ -46,6 +46,8 @@ const propTypes = {
datasource: PropTypes.object,
partitionColumn: PropTypes.string,
theme: PropTypes.object,
sections: PropTypes.arrayOf(PropTypes.string),
operators: PropTypes.arrayOf(PropTypes.string),
};
const ResizeIcon = styled.i`
@ -54,6 +56,11 @@ const ResizeIcon = styled.i`
const startingWidth = 320;
const startingHeight = 240;
const SectionWrapper = styled.div`
.ant-select {
margin-bottom: ${({ theme }) => theme.gridUnit * 4}px;
}
`;
const FilterPopoverContentContainer = styled.div`
.adhoc-filter-edit-tabs > .nav-tabs {
@ -166,15 +173,51 @@ export default class AdhocFilterEditPopover extends React.Component {
onResize,
datasource,
partitionColumn,
sections = ['SIMPLE', 'CUSTOM_SQL'],
theme,
operators,
...popoverProps
} = this.props;
const { adhocFilter } = this.state;
const resultSections =
datasource?.type === 'druid'
? sections.filter(s => s !== 'CUSTOM_SQL')
: sections;
const stateIsValid = adhocFilter.isValid();
const hasUnsavedChanges = !adhocFilter.equals(propsAdhocFilter);
const sectionRenders = {};
sectionRenders.CUSTOM_SQL = (
<ErrorBoundary>
<AdhocFilterEditPopoverSqlTabContent
adhocFilter={this.state.adhocFilter}
onChange={this.onAdhocFilterChange}
options={this.props.options}
height={this.state.height}
activeKey={this.state.activeKey}
/>
</ErrorBoundary>
);
sectionRenders.SIMPLE = (
<ErrorBoundary>
<AdhocFilterEditPopoverSimpleTabContent
operators={operators}
adhocFilter={this.state.adhocFilter}
onChange={this.onAdhocFilterChange}
options={options}
datasource={datasource}
onHeightChange={this.adjustHeight}
partitionColumn={partitionColumn}
popoverRef={this.popoverContentRef.current}
/>
</ErrorBoundary>
);
return (
<FilterPopoverContentContainer
id="filter-edit-popover"
@ -182,55 +225,38 @@ export default class AdhocFilterEditPopover extends React.Component {
data-test="filter-edit-popover"
ref={this.popoverContentRef}
>
<Tabs
id="adhoc-filter-edit-tabs"
defaultActiveKey={adhocFilter.expressionType}
className="adhoc-filter-edit-tabs"
data-test="adhoc-filter-edit-tabs"
style={{ minHeight: this.state.height, width: this.state.width }}
allowOverflow
onChange={this.onTabChange}
>
<Tabs.TabPane
className="adhoc-filter-edit-tab"
key={EXPRESSION_TYPES.SIMPLE}
tab={t('Simple')}
{resultSections.length > 1 ? (
<Tabs
id="adhoc-filter-edit-tabs"
defaultActiveKey={adhocFilter.expressionType}
className="adhoc-filter-edit-tabs"
data-test="adhoc-filter-edit-tabs"
style={{ minHeight: this.state.height, width: this.state.width }}
allowOverflow
onChange={this.onTabChange}
>
<ErrorBoundary>
<AdhocFilterEditPopoverSimpleTabContent
adhocFilter={this.state.adhocFilter}
onChange={this.onAdhocFilterChange}
options={options}
datasource={datasource}
onHeightChange={this.adjustHeight}
partitionColumn={partitionColumn}
popoverRef={this.popoverContentRef.current}
/>
</ErrorBoundary>
</Tabs.TabPane>
<Tabs.TabPane
className="adhoc-filter-edit-tab"
key={EXPRESSION_TYPES.SQL}
tab={t('Custom SQL')}
>
<ErrorBoundary>
{!this.props.datasource ||
this.props.datasource.type !== 'druid' ? (
<AdhocFilterEditPopoverSqlTabContent
adhocFilter={this.state.adhocFilter}
onChange={this.onAdhocFilterChange}
options={this.props.options}
height={this.state.height}
activeKey={this.state.activeKey}
/>
) : (
<div className="custom-sql-disabled-message">
Custom SQL Filters are not available on druid datasources
</div>
)}
</ErrorBoundary>
</Tabs.TabPane>
</Tabs>
{resultSections.includes('SIMPLE') && (
<Tabs.TabPane
className="adhoc-filter-edit-tab"
key={EXPRESSION_TYPES.SIMPLE}
tab={t('Simple')}
>
{sectionRenders.SIMPLE}
</Tabs.TabPane>
)}
{resultSections.includes('CUSTOM_SQL') && (
<Tabs.TabPane
className="adhoc-filter-edit-tab"
key={EXPRESSION_TYPES.SQL}
tab={t('Custom SQL')}
>
{sectionRenders.CUSTOM_SQL}
</Tabs.TabPane>
)}
</Tabs>
) : (
<SectionWrapper>{sectionRenders[resultSections[0]]}</SectionWrapper>
)}
<div>
<Button buttonSize="small" onClick={this.props.onClose} cta>
{t('Close')}

View File

@ -38,6 +38,20 @@ import AdhocFilter, {
} from 'src/explore/components/controls/FilterControl/AdhocFilter';
import { Input } from 'src/common/components';
const StyledInput = styled(Input)`
margin-bottom: ${({ theme }) => theme.gridUnit * 4}px;
`;
const SelectWithLabel = styled(Select)<{ labelText: string }>`
.ant-select-selector::after {
content: ${({ labelText }) => labelText || '\\A0'};
display: inline-block;
white-space: nowrap;
color: ${({ theme }) => theme.colors.grayscale.light1};
width: max-content;
}
`;
export interface SimpleColumnType {
id: number;
column_name: string;
@ -81,6 +95,7 @@ export interface Props {
filter_select: boolean;
};
partitionColumn: string;
operators?: Operators[];
}
export const useSimpleTabFilterProps = (props: Props) => {
const isOperatorRelevant = (operator: Operators, subject: string) => {
@ -280,7 +295,9 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
const operatorSelectProps = {
placeholder: t(
'%s operator(s)',
OPERATORS_OPTIONS.filter(op => isOperatorRelevant(op, subject)).length,
(props.operators ?? OPERATORS_OPTIONS).filter(op =>
isOperatorRelevant(op, subject),
).length,
),
value: operatorId,
onChange: onOperatorChange,
@ -310,16 +327,6 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
const labelText =
comparator && comparator.length > 0 && createSuggestionsPlaceholder();
const SelectWithLabel = styled(Select)`
.ant-select-selector::after {
content: ${() => labelText || '\\A0'};
display: inline-block;
white-space: nowrap;
color: ${({ theme }) => theme.colors.grayscale.light1};
width: max-content;
}
`;
useEffect(() => {
const refreshComparatorSuggestions = () => {
const { datasource } = props;
@ -380,17 +387,18 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
/>
<Select
css={theme => ({ marginBottom: theme.gridUnit * 4 })}
options={OPERATORS_OPTIONS.filter(op =>
isOperatorRelevant(op, subject),
).map(option => ({
value: option,
label: OPERATOR_ENUM_TO_OPERATOR_TYPE[option].display,
key: option,
}))}
options={(props.operators ?? OPERATORS_OPTIONS)
.filter(op => isOperatorRelevant(op, subject))
.map(option => ({
value: option,
label: OPERATOR_ENUM_TO_OPERATOR_TYPE[option].display,
key: option,
}))}
{...operatorSelectProps}
/>
{MULTI_OPERATORS.has(operatorId) || suggestions.length > 0 ? (
<SelectWithLabel
labelText={labelText}
options={suggestions.map((suggestion: string) => ({
value: suggestion,
label: String(suggestion),
@ -398,7 +406,7 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC<Props> = props => {
{...comparatorSelectProps}
/>
) : (
<Input
<StyledInput
data-test="adhoc-filter-simple-value"
name="filter-value"
ref={ref => {

View File

@ -36,6 +36,8 @@ const propTypes = {
adhocMetricType,
]),
).isRequired,
sections: PropTypes.arrayOf(PropTypes.string),
operators: PropTypes.arrayOf(PropTypes.string),
datasource: PropTypes.object,
partitionColumn: PropTypes.string,
onMoveLabel: PropTypes.func,
@ -53,8 +55,12 @@ const AdhocFilterOption = ({
onMoveLabel,
onDropLabel,
index,
sections,
operators,
}) => (
<AdhocFilterPopoverTrigger
sections={sections}
operators={operators}
adhocFilter={adhocFilter}
options={options}
datasource={datasource}

View File

@ -22,8 +22,11 @@ import { OptionSortType } from 'src/explore/types';
import AdhocFilterEditPopover from 'src/explore/components/controls/FilterControl/AdhocFilterEditPopover';
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
import { ExplorePopoverContent } from 'src/explore/components/ExploreContentPopover';
import { Operators } from 'src/explore/constants';
interface AdhocFilterPopoverTriggerProps {
sections?: string[];
operators?: Operators[];
adhocFilter: AdhocFilter;
options: OptionSortType[];
datasource: Record<string, any>;
@ -90,6 +93,8 @@ class AdhocFilterPopoverTrigger extends React.PureComponent<
partitionColumn={this.props.partitionColumn}
onResize={this.onPopoverResize}
onClose={closePopover}
sections={this.props.sections}
operators={this.props.operators}
onChange={this.props.onFilterEdit}
/>
</ExplorePopoverContent>