Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(explore): Implement metrics and columns popovers empty states #18681

Merged
merged 3 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ export const dnd_granularity_sqla: typeof dndGroupByControl = {
options,
default:
datasource?.main_dttm_col || temporalColumns[0]?.column_name || null,
isTemporal: true,
};
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ import { Select } from 'src/components';

import { Form, FormItem } from 'src/components/Form';
import { SQLEditor } from 'src/components/AsyncAceEditor';
import { EmptyStateSmall } from 'src/components/EmptyState';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
import { POPOVER_INITIAL_HEIGHT } from 'src/explore/constants';
import {
POPOVER_INITIAL_HEIGHT,
UNRESIZABLE_POPOVER_WIDTH,
} from 'src/explore/constants';

const StyledSelect = styled(Select)`
.metric-option {
Expand All @@ -59,6 +63,7 @@ interface ColumnSelectPopoverProps {
setLabel: (title: string) => void;
getCurrentTab: (tab: string) => void;
label: string;
isTemporal?: boolean;
}

const getInitialColumnValues = (
Expand All @@ -84,6 +89,7 @@ const ColumnSelectPopover = ({
setLabel,
getCurrentTab,
label,
isTemporal,
}: ColumnSelectPopoverProps) => {
const [initialLabel] = useState(label);
const [initialAdhocColumn, initialCalculatedColumn, initialSimpleColumn] =
Expand Down Expand Up @@ -234,48 +240,80 @@ const ColumnSelectPopover = ({
allowOverflow
css={css`
height: ${POPOVER_INITIAL_HEIGHT}px;
width: ${UNRESIZABLE_POPOVER_WIDTH}px;
`}
>
<Tabs.TabPane key="saved" tab={t('Saved')}>
<FormItem label={savedExpressionsLabel}>
<StyledSelect
ariaLabel={savedExpressionsLabel}
value={selectedCalculatedColumn?.column_name}
onChange={onCalculatedColumnChange}
allowClear
autoFocus={!selectedCalculatedColumn}
placeholder={t('%s column(s)', calculatedColumns.length)}
options={calculatedColumns.map(calculatedColumn => ({
value: calculatedColumn.column_name,
label:
calculatedColumn.verbose_name || calculatedColumn.column_name,
customLabel: (
<StyledColumnOption column={calculatedColumn} showType />
),
key: calculatedColumn.column_name,
}))}
{calculatedColumns.length > 0 ? (
<FormItem label={savedExpressionsLabel}>
<StyledSelect
ariaLabel={savedExpressionsLabel}
value={selectedCalculatedColumn?.column_name}
onChange={onCalculatedColumnChange}
allowClear
autoFocus={!selectedCalculatedColumn}
placeholder={t('%s column(s)', calculatedColumns.length)}
options={calculatedColumns.map(calculatedColumn => ({
value: calculatedColumn.column_name,
label:
calculatedColumn.verbose_name ||
calculatedColumn.column_name,
customLabel: (
<StyledColumnOption column={calculatedColumn} showType />
),
key: calculatedColumn.column_name,
}))}
/>
</FormItem>
) : (
<EmptyStateSmall
image="empty.svg"
title={
isTemporal
? t('No temporal columns found')
: t('No saved expressions found')
}
description={
isTemporal
? t(
'Add calculated temporal columns to dataset in "Edit datasource" modal',
)
: t(
'Add calculated columns to dataset in "Edit datasource" modal',
)
}
/>
</FormItem>
)}
</Tabs.TabPane>
<Tabs.TabPane key="simple" tab={t('Simple')}>
<FormItem label={simpleColumnsLabel}>
<Select
ariaLabel={simpleColumnsLabel}
value={selectedSimpleColumn?.column_name}
onChange={onSimpleColumnChange}
allowClear
autoFocus={!selectedSimpleColumn}
placeholder={t('%s column(s)', simpleColumns.length)}
options={simpleColumns.map(simpleColumn => ({
value: simpleColumn.column_name,
label: simpleColumn.verbose_name || simpleColumn.column_name,
customLabel: (
<StyledColumnOption column={simpleColumn} showType />
),
key: simpleColumn.column_name,
}))}
{isTemporal && simpleColumns.length === 0 ? (
<EmptyStateSmall
image="empty.svg"
title={t('No temporal columns found')}
description={t(
'Mark a column as temporal in "Edit datasource" modal',
)}
/>
</FormItem>
) : (
<FormItem label={simpleColumnsLabel}>
<Select
ariaLabel={simpleColumnsLabel}
value={selectedSimpleColumn?.column_name}
onChange={onSimpleColumnChange}
allowClear
autoFocus={!selectedSimpleColumn}
placeholder={t('%s column(s)', simpleColumns.length)}
options={simpleColumns.map(simpleColumn => ({
value: simpleColumn.column_name,
label: simpleColumn.verbose_name || simpleColumn.column_name,
customLabel: (
<StyledColumnOption column={simpleColumn} showType />
),
key: simpleColumn.column_name,
}))}
/>
</FormItem>
)}
</Tabs.TabPane>

<Tabs.TabPane key="sqlExpression" tab={t('Custom SQL')}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface ColumnSelectPopoverTriggerProps {
togglePopover?: (visible: boolean) => void;
closePopover?: () => void;
children: React.ReactNode;
isTemporal?: boolean;
}

const defaultPopoverLabel = t('My column');
Expand All @@ -48,6 +49,7 @@ const ColumnSelectPopoverTrigger = ({
onColumnEdit,
isControlledComponent,
children,
isTemporal,
...props
}: ColumnSelectPopoverTriggerProps) => {
const [popoverLabel, setPopoverLabel] = useState(defaultPopoverLabel);
Expand Down Expand Up @@ -102,6 +104,7 @@ const ColumnSelectPopoverTrigger = ({
label={popoverLabel}
setLabel={setPopoverLabel}
getCurrentTab={getCurrentTab}
isTemporal={isTemporal}
/>
</ExplorePopoverContent>
),
Expand All @@ -110,6 +113,7 @@ const ColumnSelectPopoverTrigger = ({
editedColumn,
getCurrentTab,
handleClosePopover,
isTemporal,
onColumnEdit,
popoverLabel,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { DndControlProps } from './types';

export type DndColumnSelectProps = DndControlProps<QueryFormColumn> & {
options: Record<string, ColumnMeta>;
isTemporal?: boolean;
};

export function DndColumnSelect(props: DndColumnSelectProps) {
Expand All @@ -49,6 +50,7 @@ export function DndColumnSelect(props: DndColumnSelectProps) {
ghostButtonText,
name,
label,
isTemporal,
} = props;
const [newColumnPopoverVisible, setNewColumnPopoverVisible] = useState(false);

Expand Down Expand Up @@ -151,6 +153,7 @@ export function DndColumnSelect(props: DndColumnSelectProps) {
onChange(optionSelector.getValues());
}}
editedColumn={column}
isTemporal={isTemporal}
>
<OptionWrapper
key={idx}
Expand Down Expand Up @@ -244,6 +247,7 @@ export function DndColumnSelect(props: DndColumnSelectProps) {
togglePopover={togglePopover}
closePopover={closePopover}
visible={newColumnPopoverVisible}
isTemporal={isTemporal}
>
<div />
</ColumnSelectPopoverTrigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ const sqlExpressionAdhocMetric = new AdhocMetric({
function setup(overrides) {
const onChange = sinon.spy();
const onClose = sinon.spy();
const savedMetric = { metric_name: 'foo', expression: 'COUNT(*)' };
const props = {
adhocMetric: sumValueAdhocMetric,
savedMetric: { metric_name: 'foo', expression: 'COUNT(*)' },
savedMetrics: [],
savedMetric,
savedMetricsOptions: [savedMetric],
onChange,
onClose,
onResize: () => {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,16 @@
/* eslint-disable camelcase */
import React from 'react';
import PropTypes from 'prop-types';
import { t, styled, ensureIsArray } from '@superset-ui/core';
import Tabs from 'src/components/Tabs';
import Button from 'src/components/Button';
import { Select } from 'src/components';
import { Tooltip } from 'src/components/Tooltip';
import { t, styled } from '@superset-ui/core';

import { EmptyStateSmall } from 'src/components/EmptyState';
import { Form, FormItem } from 'src/components/Form';
import { SQLEditor } from 'src/components/AsyncAceEditor';
import sqlKeywords from 'src/SqlLab/utils/sqlKeywords';
import { noOp } from 'src/utils/common';

import {
AGGREGATES_OPTIONS,
POPOVER_INITIAL_HEIGHT,
Expand Down Expand Up @@ -366,21 +365,29 @@ export default class AdhocMetricEditPopover extends React.PureComponent {
allowOverflow
>
<Tabs.TabPane key={SAVED_TAB_KEY} tab={t('Saved')}>
<FormItem label={t('Saved metric')}>
<StyledSelect
options={
Array.isArray(savedMetricsOptions)
? savedMetricsOptions.map(savedMetric => ({
value: savedMetric.metric_name,
label: savedMetric.metric_name,
customLabel: this.renderMetricOption(savedMetric),
key: savedMetric.id,
}))
: []
}
{...savedSelectProps}
{ensureIsArray(savedMetricsOptions).length > 0 ? (
<FormItem label={t('Saved metric')}>
<StyledSelect
options={ensureIsArray(savedMetricsOptions).map(
savedMetric => ({
value: savedMetric.metric_name,
label: savedMetric.metric_name,
customLabel: this.renderMetricOption(savedMetric),
key: savedMetric.id,
}),
)}
{...savedSelectProps}
/>
</FormItem>
) : (
<EmptyStateSmall
image="empty.svg"
title={t('No saved metrics found')}
description={t(
'Add metrics to dataset in "Edit datasource" modal',
)}
/>
</FormItem>
)}
</Tabs.TabPane>
<Tabs.TabPane
key={EXPRESSION_TYPES.SIMPLE}
Expand Down
1 change: 1 addition & 0 deletions superset-frontend/src/explore/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,4 @@ export const FILTER_BOX_TRANSITION_SNOOZE_DURATION = 24 * 60 * 60 * 1000; // 24

export const POPOVER_INITIAL_HEIGHT = 240;
export const POPOVER_INITIAL_WIDTH = 320;
export const UNRESIZABLE_POPOVER_WIDTH = 296;