Skip to content

Commit

Permalink
feat(explore): Implement metrics and columns popovers empty states (#…
Browse files Browse the repository at this point in the history
…18681)

* feat(explore): Implement empty states for column and metrics popovers

* Fix test

* Change copy
  • Loading branch information
kgabryje committed Feb 14, 2022
1 parent f8b3ece commit c1205b5
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 55 deletions.
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;

0 comments on commit c1205b5

Please sign in to comment.