diff --git a/superset-frontend/images/icons/alert_solid_small.svg b/superset-frontend/images/icons/alert_solid_small.svg new file mode 100644 index 0000000000000..092c37f1ce9a5 --- /dev/null +++ b/superset-frontend/images/icons/alert_solid_small.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/superset-frontend/images/icons/slack.svg b/superset-frontend/images/icons/slack.svg index 3d10ce6cce277..3ee9ffd93e2d9 100644 --- a/superset-frontend/images/icons/slack.svg +++ b/superset-frontend/images/icons/slack.svg @@ -16,12 +16,13 @@ specific language governing permissions and limitations under the License. --> - - - - - - - - + + + + + + + + + diff --git a/superset-frontend/src/components/Icon/index.tsx b/superset-frontend/src/components/Icon/index.tsx index ceeb9598c6912..5a5f336cfbd95 100644 --- a/superset-frontend/src/components/Icon/index.tsx +++ b/superset-frontend/src/components/Icon/index.tsx @@ -20,6 +20,7 @@ import React, { SVGProps } from 'react'; import { ReactComponent as AlertIcon } from 'images/icons/alert.svg'; import { ReactComponent as AlertSolidIcon } from 'images/icons/alert_solid.svg'; +import { ReactComponent as AlertSolidSmallIcon } from 'images/icons/alert_solid_small.svg'; import { ReactComponent as BinocularsIcon } from 'images/icons/binoculars.svg'; import { ReactComponent as BoltIcon } from 'images/icons/bolt.svg'; import { ReactComponent as BoltSmallIcon } from 'images/icons/bolt_small.svg'; @@ -144,6 +145,7 @@ import { ReactComponent as XSmallIcon } from 'images/icons/x-small.svg'; export type IconName = | 'alert' | 'alert-solid' + | 'alert-solid-small' | 'binoculars' | 'bolt' | 'bolt-small' @@ -270,6 +272,7 @@ export const iconsRegistry: Record< React.ComponentType> > = { 'alert-solid': AlertSolidIcon, + 'alert-solid-small': AlertSolidSmallIcon, 'bolt-small': BoltSmallIcon, 'bolt-small-run': BoltSmallRunIcon, 'cancel-solid': CancelSolidIcon, diff --git a/superset-frontend/src/views/CRUD/alert/AlertList.tsx b/superset-frontend/src/views/CRUD/alert/AlertList.tsx index 767686553da5c..83d352b871abf 100644 --- a/superset-frontend/src/views/CRUD/alert/AlertList.tsx +++ b/superset-frontend/src/views/CRUD/alert/AlertList.tsx @@ -20,6 +20,7 @@ import React, { useState, useMemo, useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { t, SupersetClient, makeApi, styled } from '@superset-ui/core'; +import moment from 'moment'; import ActionsBar, { ActionProps } from 'src/components/ListView/ActionsBar'; import Button from 'src/components/Button'; import FacePile from 'src/components/FacePile'; @@ -32,6 +33,7 @@ import ListView, { } from 'src/components/ListView'; import SubMenu, { SubMenuProps } from 'src/components/Menu/SubMenu'; import { Switch } from 'src/common/components/Switch'; +import { DATETIME_WITH_TIME_ZONE } from 'src/constants'; import withToasts from 'src/messageToasts/enhancers/withToasts'; import AlertStatusIcon from 'src/views/CRUD/alert/components/AlertStatusIcon'; import RecipientIcon from 'src/views/CRUD/alert/components/RecipientIcon'; @@ -192,27 +194,33 @@ function AlertList({ row: { original: { last_state: lastState }, }, - }: any) => , + }: any) => ( + + ), accessor: 'last_state', size: 'xs', disableSortBy: true, }, - { - accessor: 'name', - Header: t('Name'), - }, { Cell: ({ row: { - original: { recipients }, + original: { last_eval_dttm: lastEvalDttm }, }, - }: any) => - recipients.map((r: any) => ( - - )), - accessor: 'recipients', - Header: t('Notification Method'), - disableSortBy: true, + }: any) => { + return lastEvalDttm + ? moment.utc(lastEvalDttm).local().format(DATETIME_WITH_TIME_ZONE) + : ''; + }, + accessor: 'last_eval_dttm', + Header: t('Last Run'), + size: 'lg', + }, + { + accessor: 'name', + Header: t('Name'), size: 'xl', }, { @@ -229,6 +237,20 @@ function AlertList({ ), }, + { + Cell: ({ + row: { + original: { recipients }, + }, + }: any) => + recipients.map((r: any) => ( + + )), + accessor: 'recipients', + Header: t('Notification Method'), + disableSortBy: true, + size: 'xl', + }, { accessor: 'created_by', disableSortBy: true, @@ -307,7 +329,7 @@ function AlertList({ size: 'xl', }, ], - [canDelete, canEdit], + [canDelete, canEdit, isReportEnabled], ); const subMenuButtons: SubMenuProps['buttons'] = []; diff --git a/superset-frontend/src/views/CRUD/alert/ExecutionLog.tsx b/superset-frontend/src/views/CRUD/alert/ExecutionLog.tsx index fe5966abd41d9..5806255ba4e50 100644 --- a/superset-frontend/src/views/CRUD/alert/ExecutionLog.tsx +++ b/superset-frontend/src/views/CRUD/alert/ExecutionLog.tsx @@ -87,7 +87,9 @@ function ExecutionLog({ addDangerToast, isReportEnabled }: ExecutionLogProps) { row: { original: { state }, }, - }: any) => , + }: any) => ( + + ), accessor: 'state', Header: t('State'), size: 'xs', @@ -125,7 +127,7 @@ function ExecutionLog({ addDangerToast, isReportEnabled }: ExecutionLogProps) { Header: t('Error Message'), }, ], - [], + [isReportEnabled], ); const path = `/${isReportEnabled ? 'report' : 'alert'}/list/`; return ( diff --git a/superset-frontend/src/views/CRUD/alert/components/AlertStatusIcon.tsx b/superset-frontend/src/views/CRUD/alert/components/AlertStatusIcon.tsx index cb6d3a08fded5..6bbfa06c68f27 100644 --- a/superset-frontend/src/views/CRUD/alert/components/AlertStatusIcon.tsx +++ b/superset-frontend/src/views/CRUD/alert/components/AlertStatusIcon.tsx @@ -22,22 +22,34 @@ import { Tooltip } from 'src/common/components/Tooltip'; import Icon, { IconName } from 'src/components/Icon'; import { AlertState } from '../types'; -const StatusIcon = styled(Icon)<{ status: string }>` - color: ${({ status, theme }) => { +const StatusIcon = styled(Icon)<{ status: string; isReportEnabled: boolean }>` + color: ${({ status, theme, isReportEnabled }) => { switch (status) { case AlertState.working: - return theme.colors.alert.base; + return theme.colors.primary.base; case AlertState.error: return theme.colors.error.base; case AlertState.success: + return isReportEnabled + ? theme.colors.success.base + : theme.colors.alert.base; + case AlertState.noop: return theme.colors.success.base; + case AlertState.grace: + return theme.colors.alert.base; default: return theme.colors.grayscale.base; } }}; `; -export default function AlertStatusIcon({ state }: { state: string }) { +export default function AlertStatusIcon({ + state, + isReportEnabled = false, +}: { + state: string; + isReportEnabled: boolean; +}) { const lastStateConfig = { name: '', label: '', @@ -45,30 +57,52 @@ export default function AlertStatusIcon({ state }: { state: string }) { }; switch (state) { case AlertState.success: - lastStateConfig.name = 'check'; - lastStateConfig.label = t(`${AlertState.success}`); + lastStateConfig.name = isReportEnabled ? 'check' : 'alert-solid-small'; + lastStateConfig.label = isReportEnabled + ? t('Report Sent') + : t('Alert Triggered, Notification Sent'); lastStateConfig.status = AlertState.success; break; case AlertState.working: - lastStateConfig.name = 'exclamation'; - lastStateConfig.label = t(`${AlertState.working}`); + lastStateConfig.name = 'running'; + lastStateConfig.label = isReportEnabled + ? t('Report Sending') + : t('Alert Running'); lastStateConfig.status = AlertState.working; break; case AlertState.error: lastStateConfig.name = 'x-small'; - lastStateConfig.label = t(`${AlertState.error}`); + lastStateConfig.label = isReportEnabled + ? t('Report Failed') + : t('Alert Failed'); lastStateConfig.status = AlertState.error; break; + case AlertState.noop: + lastStateConfig.name = 'check'; + lastStateConfig.label = t('Nothing Triggered'); + lastStateConfig.status = AlertState.noop; + break; + case AlertState.grace: + lastStateConfig.name = 'alert-solid-small'; + lastStateConfig.label = t('Alert Triggered, In Grace Period'); + lastStateConfig.status = AlertState.grace; + break; default: - lastStateConfig.name = 'exclamation'; - lastStateConfig.label = t(`${AlertState.working}`); - lastStateConfig.status = AlertState.working; + lastStateConfig.name = 'check'; + lastStateConfig.label = t('Nothing Triggered'); + lastStateConfig.status = AlertState.noop; } return ( - + ); diff --git a/superset-frontend/src/views/CRUD/alert/components/RecipientIcon.tsx b/superset-frontend/src/views/CRUD/alert/components/RecipientIcon.tsx index d437488e065f4..606d05a6f9b88 100644 --- a/superset-frontend/src/views/CRUD/alert/components/RecipientIcon.tsx +++ b/superset-frontend/src/views/CRUD/alert/components/RecipientIcon.tsx @@ -16,12 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -import { t } from '@superset-ui/core'; +import { styled, t } from '@superset-ui/core'; import React from 'react'; import { Tooltip } from 'src/common/components/Tooltip'; import Icon, { IconName } from 'src/components/Icon'; import { RecipientIconName } from '../types'; +const StyledIcon = styled(Icon)` + color: ${({ theme }) => theme.colors.grayscale.light1}; + margin-right: ${({ theme }) => theme.gridUnit * 2}px; +`; + export default function RecipientIcon({ type }: { type: string }) { const recipientIconConfig = { name: '', @@ -42,7 +47,7 @@ export default function RecipientIcon({ type }: { type: string }) { } return recipientIconConfig.name.length ? ( - + ) : null; }