Skip to content

Commit

Permalink
feat(CRUD): add new empty state (#19310)
Browse files Browse the repository at this point in the history
* feat(CRUD): add new empty state

* fix ci

* add svg license
  • Loading branch information
stephenLYZ committed Apr 11, 2022
1 parent f21ba68 commit d49fd01
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 87 deletions.
34 changes: 34 additions & 0 deletions superset-frontend/src/assets/images/filter-results.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions superset-frontend/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface ButtonProps {
| 'rightTop'
| 'rightBottom';
onClick?: OnClickHandler;
onMouseDown?: OnClickHandler;
disabled?: boolean;
buttonStyle?: ButtonStyle;
buttonSize?: 'default' | 'small' | 'xsmall';
Expand Down
19 changes: 16 additions & 3 deletions superset-frontend/src/components/EmptyState/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import React, { ReactNode } from 'react';
import React, { ReactNode, SyntheticEvent } from 'react';
import { styled, css, SupersetTheme } from '@superset-ui/core';
import { Empty } from 'src/components';
import Button from 'src/components/Button';
Expand Down Expand Up @@ -140,6 +140,11 @@ const ImageContainer = ({ image, size }: ImageContainerProps) => (
/>
);

const handleMouseDown = (e: SyntheticEvent) => {
e.preventDefault();
e.stopPropagation();
};

export const EmptyStateBig = ({
title,
image,
Expand All @@ -159,7 +164,11 @@ export const EmptyStateBig = ({
<BigTitle>{title}</BigTitle>
{description && <BigDescription>{description}</BigDescription>}
{buttonAction && buttonText && (
<ActionButton buttonStyle="primary" onClick={buttonAction}>
<ActionButton
buttonStyle="primary"
onClick={buttonAction}
onMouseDown={handleMouseDown}
>
{buttonText}
</ActionButton>
)}
Expand All @@ -186,7 +195,11 @@ export const EmptyStateMedium = ({
<Title>{title}</Title>
{description && <Description>{description}</Description>}
{buttonText && buttonAction && (
<ActionButton buttonStyle="primary" onClick={buttonAction}>
<ActionButton
buttonStyle="primary"
onClick={buttonAction}
onMouseDown={handleMouseDown}
>
{buttonText}
</ActionButton>
)}
Expand Down
4 changes: 4 additions & 0 deletions superset-frontend/src/components/ListView/Filters/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ export const FilterContainer = styled.div`
align-items: center;
width: ${SELECT_WIDTH}px;
`;

export type FilterHandler = {
clearFilter: () => void;
};
27 changes: 20 additions & 7 deletions superset-frontend/src/components/ListView/Filters/DateRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useMemo } from 'react';
import React, {
useState,
useMemo,
forwardRef,
useImperativeHandle,
} from 'react';
import moment, { Moment } from 'moment';
import { styled } from '@superset-ui/core';
import { RangePicker } from 'src/components/DatePicker';
import { FormLabel } from 'src/components/Form';
import { BaseFilter } from './Base';
import { BaseFilter, FilterHandler } from './Base';

interface DateRangeFilterProps extends BaseFilter {
onSubmit: (val: number[]) => void;
Expand All @@ -38,17 +43,23 @@ const RangeFilterContainer = styled.div`
width: 360px;
`;

export default function DateRangeFilter({
Header,
initialValue,
onSubmit,
}: DateRangeFilterProps) {
function DateRangeFilter(
{ Header, initialValue, onSubmit }: DateRangeFilterProps,
ref: React.RefObject<FilterHandler>,
) {
const [value, setValue] = useState<ValueState | null>(initialValue ?? null);
const momentValue = useMemo((): [Moment, Moment] | null => {
if (!value || (Array.isArray(value) && !value.length)) return null;
return [moment(value[0]), moment(value[1])];
}, [value]);

useImperativeHandle(ref, () => ({
clearFilter: () => {
setValue(null);
onSubmit([]);
},
}));

return (
<RangeFilterContainer>
<FormLabel>{Header}</FormLabel>
Expand All @@ -72,3 +83,5 @@ export default function DateRangeFilter({
</RangeFilterContainer>
);
}

export default forwardRef(DateRangeFilter);
23 changes: 15 additions & 8 deletions superset-frontend/src/components/ListView/Filters/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState } from 'react';
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import { t, styled } from '@superset-ui/core';
import Icons from 'src/components/Icons';
import { AntdInput } from 'src/components';
import { SELECT_WIDTH } from 'src/components/ListView/utils';
import { FormLabel } from 'src/components/Form';
import { BaseFilter } from './Base';
import { BaseFilter, FilterHandler } from './Base';

interface SearchHeaderProps extends BaseFilter {
Header: string;
Expand All @@ -42,12 +42,10 @@ const StyledInput = styled(AntdInput)`
border-radius: ${({ theme }) => theme.gridUnit}px;
`;

export default function SearchFilter({
Header,
name,
initialValue,
onSubmit,
}: SearchHeaderProps) {
function SearchFilter(
{ Header, name, initialValue, onSubmit }: SearchHeaderProps,
ref: React.RefObject<FilterHandler>,
) {
const [value, setValue] = useState(initialValue || '');
const handleSubmit = () => {
if (value) {
Expand All @@ -61,6 +59,13 @@ export default function SearchFilter({
}
};

useImperativeHandle(ref, () => ({
clearFilter: () => {
setValue('');
onSubmit('');
},
}));

return (
<Container>
<FormLabel>{Header}</FormLabel>
Expand All @@ -78,3 +83,5 @@ export default function SearchFilter({
</Container>
);
}

export default forwardRef(SearchFilter);
36 changes: 25 additions & 11 deletions superset-frontend/src/components/ListView/Filters/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useMemo } from 'react';
import React, {
useState,
useMemo,
forwardRef,
useImperativeHandle,
} from 'react';
import { t } from '@superset-ui/core';
import { Select } from 'src/components';
import { Filter, SelectOption } from 'src/components/ListView/types';
import { FormLabel } from 'src/components/Form';
import { FilterContainer, BaseFilter } from './Base';
import { FilterContainer, BaseFilter, FilterHandler } from './Base';

interface SelectFilterProps extends BaseFilter {
fetchSelects?: Filter['fetchSelects'];
Expand All @@ -31,14 +36,17 @@ interface SelectFilterProps extends BaseFilter {
selects: Filter['selects'];
}

function SelectFilter({
Header,
name,
fetchSelects,
initialValue,
onSelect,
selects = [],
}: SelectFilterProps) {
function SelectFilter(
{
Header,
name,
fetchSelects,
initialValue,
onSelect,
selects = [],
}: SelectFilterProps,
ref: React.RefObject<FilterHandler>,
) {
const [selectedOption, setSelectedOption] = useState(initialValue);

const onChange = (selected: SelectOption) => {
Expand All @@ -53,6 +61,12 @@ function SelectFilter({
setSelectedOption(undefined);
};

useImperativeHandle(ref, () => ({
clearFilter: () => {
onClear();
},
}));

const fetchAndFormatSelects = useMemo(
() => async (inputValue: string, page: number, pageSize: number) => {
if (fetchSelects) {
Expand Down Expand Up @@ -88,4 +102,4 @@ function SelectFilter({
</FilterContainer>
);
}
export default SelectFilter;
export default forwardRef(SelectFilter);
36 changes: 29 additions & 7 deletions superset-frontend/src/components/ListView/Filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import React, {
createRef,
forwardRef,
useImperativeHandle,
useMemo,
} from 'react';
import { withTheme } from '@superset-ui/core';

import {
Expand All @@ -28,18 +33,32 @@ import {
import SearchFilter from './Search';
import SelectFilter from './Select';
import DateRangeFilter from './DateRange';
import { FilterHandler } from './Base';

interface UIFiltersProps {
filters: Filters;
internalFilters: InternalFilter[];
updateFilterValue: (id: number, value: FilterValue['value']) => void;
}

function UIFilters({
filters,
internalFilters = [],
updateFilterValue,
}: UIFiltersProps) {
function UIFilters(
{ filters, internalFilters = [], updateFilterValue }: UIFiltersProps,
ref: React.RefObject<{ clearFilters: () => void }>,
) {
const filterRefs = useMemo(
() =>
Array.from({ length: filters.length }, () => createRef<FilterHandler>()),
[filters.length],
);

useImperativeHandle(ref, () => ({
clearFilters: () => {
filterRefs.forEach((filter: any) => {
filter.current?.clearFilter?.();
});
},
}));

return (
<>
{filters.map(
Expand All @@ -49,6 +68,7 @@ function UIFilters({
if (input === 'select') {
return (
<SelectFilter
ref={filterRefs[index]}
Header={Header}
fetchSelects={fetchSelects}
initialValue={initialValue}
Expand All @@ -65,6 +85,7 @@ function UIFilters({
if (input === 'search' && typeof Header === 'string') {
return (
<SearchFilter
ref={filterRefs[index]}
Header={Header}
initialValue={initialValue}
key={id}
Expand All @@ -76,6 +97,7 @@ function UIFilters({
if (input === 'datetime_range') {
return (
<DateRangeFilter
ref={filterRefs[index]}
Header={Header}
initialValue={initialValue}
key={id}
Expand All @@ -91,4 +113,4 @@ function UIFilters({
);
}

export default withTheme(UIFilters);
export default withTheme(forwardRef(UIFilters));

0 comments on commit d49fd01

Please sign in to comment.