feat: filters for alerts and reports list view (#11900)

This commit is contained in:
Lily Kuang 2020-12-04 09:58:34 -08:00 committed by GitHub
parent 77d362d306
commit 60122a2b2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 20 deletions

View File

@ -62,6 +62,10 @@ const mockalerts = [...new Array(3)].map((_, i) => ({
type: 'alert', type: 'alert',
})); }));
const mockUser = {
userId: 1,
};
fetchMock.get(alertsEndpoint, { fetchMock.get(alertsEndpoint, {
ids: [2, 0, 1], ids: [2, 0, 1],
result: mockalerts, result: mockalerts,
@ -74,7 +78,7 @@ fetchMock.put(alertEndpoint, { ...mockalerts[0], active: false });
fetchMock.put(alertsEndpoint, { ...mockalerts[0], active: false }); fetchMock.put(alertsEndpoint, { ...mockalerts[0], active: false });
async function mountAndWait(props) { async function mountAndWait(props) {
const mounted = mount(<AlertList {...props} />, { const mounted = mount(<AlertList {...props} user={mockUser} />, {
context: { store }, context: { store },
}); });
await waitForComponentToPaint(mounted); await waitForComponentToPaint(mounted);

View File

@ -25,8 +25,9 @@ import Icon, { IconName } from 'src/components/Icon';
import { Tooltip } from 'src/common/components/Tooltip'; import { Tooltip } from 'src/common/components/Tooltip';
import { Switch } from 'src/common/components/Switch'; import { Switch } from 'src/common/components/Switch';
import FacePile from 'src/components/FacePile'; import FacePile from 'src/components/FacePile';
import ListView from 'src/components/ListView'; import ListView, { Filters, FilterOperators } from 'src/components/ListView';
import SubMenu, { SubMenuProps } from 'src/components/Menu/SubMenu'; import SubMenu, { SubMenuProps } from 'src/components/Menu/SubMenu';
import { createFetchRelated, createErrorHandler } from 'src/views/CRUD/utils';
import withToasts from 'src/messageToasts/enhancers/withToasts'; import withToasts from 'src/messageToasts/enhancers/withToasts';
import { import {
@ -42,16 +43,19 @@ interface AlertListProps {
addDangerToast: (msg: string) => void; addDangerToast: (msg: string) => void;
addSuccessToast: (msg: string) => void; addSuccessToast: (msg: string) => void;
isReportEnabled: boolean; isReportEnabled: boolean;
user: {
userId: string | number;
};
} }
const StatusIcon = styled(Icon)<{ status: string }>` const StatusIcon = styled(Icon)<{ status: string }>`
color: ${({ status, theme }) => { color: ${({ status, theme }) => {
switch (status) { switch (status) {
case 'alerting': case 'Working':
return '#FBC700'; return theme.colors.alert.base;
case 'failed': case 'Error':
return theme.colors.error.base; return theme.colors.error.base;
case 'ok': case 'Success':
return theme.colors.success.base; return theme.colors.success.base;
default: default:
return theme.colors.grayscale.base; return theme.colors.grayscale.base;
@ -62,14 +66,15 @@ const StatusIcon = styled(Icon)<{ status: string }>`
function AlertList({ function AlertList({
addDangerToast, addDangerToast,
isReportEnabled = false, isReportEnabled = false,
user,
}: AlertListProps) { }: AlertListProps) {
const title = isReportEnabled ? t('report') : t('alert'); const title = isReportEnabled ? t('report') : t('alert');
const initalFilters = useMemo( const initalFilters = useMemo(
() => [ () => [
{ {
id: 'type', id: 'type',
operator: 'eq', operator: FilterOperators.equals,
value: isReportEnabled ? 'report' : 'alert', value: isReportEnabled ? 'Report' : 'Alert',
}, },
], ],
[isReportEnabled], [isReportEnabled],
@ -127,25 +132,25 @@ function AlertList({
status: '', status: '',
}; };
switch (lastState) { switch (lastState) {
case 'ok': case 'Success':
lastStateConfig.name = 'check'; lastStateConfig.name = 'check';
lastStateConfig.label = t('OK'); lastStateConfig.label = t('Success');
lastStateConfig.status = 'ok'; lastStateConfig.status = 'Success';
break; break;
case 'alerting': case 'Working':
lastStateConfig.name = 'exclamation'; lastStateConfig.name = 'exclamation';
lastStateConfig.label = t('Alerting'); lastStateConfig.label = t('Working');
lastStateConfig.status = 'alerting'; lastStateConfig.status = 'Working';
break; break;
case 'failed': case 'Error':
lastStateConfig.name = 'x-small'; lastStateConfig.name = 'x-small';
lastStateConfig.label = t('Failed'); lastStateConfig.label = t('Error');
lastStateConfig.status = 'failed'; lastStateConfig.status = 'Error';
break; break;
default: default:
lastStateConfig.name = 'exclamation'; lastStateConfig.name = 'exclamation';
lastStateConfig.label = t('Alerting'); lastStateConfig.label = t('Working');
lastStateConfig.status = 'alerting'; lastStateConfig.status = 'Working';
} }
return ( return (
<Tooltip title={lastStateConfig.label} placement="bottom"> <Tooltip title={lastStateConfig.label} placement="bottom">
@ -181,6 +186,11 @@ function AlertList({
Header: t('Schedule'), Header: t('Schedule'),
accessor: 'crontab', accessor: 'crontab',
}, },
{
accessor: 'created_by',
disableSortBy: true,
hidden: true,
},
{ {
Cell: ({ Cell: ({
row: { row: {
@ -275,6 +285,46 @@ function AlertList({
slot: canCreate ? EmptyStateButton : null, slot: canCreate ? EmptyStateButton : null,
}; };
const filters: Filters = useMemo(
() => [
{
Header: t('Created By'),
id: 'created_by',
input: 'select',
operator: FilterOperators.relationOneMany,
unfilteredLabel: 'All',
fetchSelects: createFetchRelated(
'report',
'created_by',
createErrorHandler(errMsg =>
t('An error occurred while fetching created by values: %s', errMsg),
),
user.userId,
),
paginate: true,
},
{
Header: t('Status'),
id: 'last_state',
input: 'select',
operator: FilterOperators.equals,
unfilteredLabel: 'Any',
selects: [
{ label: t('Success'), value: 'Success' },
{ label: t('Working'), value: 'Working' },
{ label: t('Error'), value: 'Error' },
],
},
{
Header: t('Search'),
id: 'name',
input: 'search',
operator: FilterOperators.contains,
},
],
[],
);
return ( return (
<> <>
<SubMenu <SubMenu
@ -303,6 +353,7 @@ function AlertList({
data={alerts} data={alerts}
emptyState={emptyState} emptyState={emptyState}
fetchData={fetchData} fetchData={fetchData}
filters={filters}
initialSort={initialSort} initialSort={initialSort}
loading={loading} loading={loading}
pageSize={PAGE_SIZE} pageSize={PAGE_SIZE}

View File

@ -145,7 +145,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
"name", "name",
"type", "type",
] ]
search_columns = ["name", "active", "created_by", "type"] search_columns = ["name", "active", "created_by", "type", "last_state"]
search_filters = {"name": [ReportScheduleAllTextFilter]} search_filters = {"name": [ReportScheduleAllTextFilter]}
allowed_rel_fields = {"created_by", "chart", "dashboard"} allowed_rel_fields = {"created_by", "chart", "dashboard"}
filter_rel_fields = { filter_rel_fields = {