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

refactor(ui): improve first time alerting experience #14917

Merged
merged 13 commits into from
Sep 4, 2019
Merged
Show file tree
Hide file tree
Changes from 12 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
1. [14694](https://github.com/influxdata/influxdb/pull/14694): Add ability to find tasks by name.

### UI Improvements
1. [14917](https://github.com/influxdata/influxdb/pull/14917): Make first steps in Monitoring & Alerting more obvious
1. [14889](https://github.com/influxdata/influxdb/pull/14889): Make adding data to buckets more discoverable
1. [14709](https://github.com/influxdata/influxdb/pull/14709): Move Buckets, Telgrafs, and Scrapers pages into a tab called "Load Data" for ease of discovery
1. [14846](https://github.com/influxdata/influxdb/pull/14846): Standardize formatting of "updated at" timestamp in all resource cards
Expand Down
2 changes: 1 addition & 1 deletion ui/cypress/e2e/notificationEndpoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Notification Endpoints', () => {
const description =
'A minute, an hour, a month. Notification Endpoint is certain. The time is not.'

cy.getByTestID('alert-column--header create-endpoint').click()
cy.getByTestID('create-endpoint').click()

cy.getByTestID('endpoint-name--input')
.clear()
Expand Down
21 changes: 0 additions & 21 deletions ui/cypress/e2e/onboarding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,6 @@ describe('Onboarding', () => {
.children('.cf-button--label')
.contains('Continue')

//Check tooltips
cy.getByTestID('form-elem--orgname')
.children('[data-testid=form--label]')
.children('div.question-mark-tooltip')
.trigger('mouseenter')
.children('div[data-id=tooltip]')
.contains('An organization is')
.should($tt => {
expect($tt).to.have.class('show')
})

cy.getByTestID('form-elem--bucketname')
.children('[data-testid=form--label]')
.children('div.question-mark-tooltip')
.trigger('mouseenter')
.children('div[data-id=tooltip]')
.contains('A bucket is')
.should($tt => {
expect($tt).to.have.class('show')
})

//Input fields
cy.getByTestID('input-field--username').type(user.username)
cy.getByTestID('input-field--password').type(user.password)
Expand Down
30 changes: 30 additions & 0 deletions ui/src/alerting/components/AlertingIndex.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,33 @@
padding: 18px;
padding-top: 0;
}

/*
First time widget
------------------------------------------------------------------------------
*/

.alerting-first-time {
border: $ix-border solid $c-ocean;

h1,
h5 {
user-select: none;
color: $c-neutrino;
}
h1 {
letter-spacing: 0;
margin-top: 0;
}

h5 {
margin-bottom: 0;
line-height: 1.5em;
font-weight: 500;

strong {
font-weight: 900;
color: $g20-white;
}
}
}
10 changes: 5 additions & 5 deletions ui/src/alerting/components/AlertingIndex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ const AlertingIndex: FunctionComponent = ({children}) => {
<ChecksColumn />
</GetResources>
</GridColumn>
<GridColumn widthLG={4} widthMD={4} widthSM={4} widthXS={12}>
<GetResources resource={ResourceTypes.NotificationRules}>
<RulesColumn />
</GetResources>
</GridColumn>
<GridColumn widthLG={4} widthMD={4} widthSM={4} widthXS={12}>
<GetResources
resource={ResourceTypes.NotificationEndpoints}
>
<EndpointsColumn />
</GetResources>
</GridColumn>
<GridColumn widthLG={4} widthMD={4} widthSM={4} widthXS={12}>
<GetResources resource={ResourceTypes.NotificationRules}>
<RulesColumn />
</GetResources>
</GridColumn>
</GridRow>
</Grid>
</GetResources>
Expand Down
86 changes: 44 additions & 42 deletions ui/src/alerting/components/AlertsColumn.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,65 @@
// Libraries
import React, {FC} from 'react'
import React, {FC, ReactChild} from 'react'

// Components
import {
Button,
ComponentColor,
Panel,
InfluxColors,
DapperScrollbars,
Input,
IconFont,
FlexBox,
FlexDirection,
ComponentSize,
} from '@influxdata/clockface'
import QuestionMarkTooltip from 'src/shared/components/question_mark_tooltip/QuestionMarkTooltip'

interface Props {
title: string
testID?: string
onCreate: () => void
createButton: JSX.Element
questionMarkTooltipContents: ReactChild
}

const AlertsColumnHeader: FC<Props> = ({
children,
onCreate,
title,
testID = '',
}) => {
return (
<Panel
backgroundColor={InfluxColors.Kevlar}
className="alerting-index--column"
>
<Panel.Header>
<Panel.Title>{title}</Panel.Title>
<Button
text="Create"
icon={IconFont.Plus}
onClick={onCreate}
color={ComponentColor.Primary}
testID={`alert-column--header ${testID}`}
createButton,
questionMarkTooltipContents,
}) => (
<Panel
backgroundColor={InfluxColors.Kevlar}
className="alerting-index--column"
>
<Panel.Header>
<FlexBox direction={FlexDirection.Row} margin={ComponentSize.Small}>
<Panel.Title style={{fontSize: '17px', width: 'auto'}}>
{title}
</Panel.Title>
<QuestionMarkTooltip
testID={`${title}--question-mark`}
tipContent={questionMarkTooltipContents}
/>
</Panel.Header>
<div className="alerting-index--search">
<Input
icon={IconFont.Search}
placeholder={`Filter ${title}...`}
value=""
onChange={() => {}}
/>
</div>
<div className="alerting-index--column-body">
<DapperScrollbars
autoSize={false}
autoHide={true}
style={{width: '100%', height: '100%'}}
>
<div className="alerting-index--list">{children}</div>
</DapperScrollbars>
</div>
</Panel>
)
}
</FlexBox>
{createButton}
</Panel.Header>
<div className="alerting-index--search">
<Input
icon={IconFont.Search}
placeholder={`Filter ${title}...`}
value=""
onChange={() => {}}
/>
</div>
<div className="alerting-index--column-body">
<DapperScrollbars
autoSize={false}
autoHide={true}
style={{width: '100%', height: '100%'}}
>
<div className="alerting-index--list">{children}</div>
</DapperScrollbars>
</div>
</Panel>
)

export default AlertsColumnHeader
51 changes: 42 additions & 9 deletions ui/src/alerting/components/CheckCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,29 @@ import React, {FunctionComponent} from 'react'

//Components
import CheckCard from 'src/alerting/components/CheckCard'
import {EmptyState, ResourceList} from '@influxdata/clockface'
import {EmptyState, ResourceList, Panel, Gradients} from '@influxdata/clockface'

// Types
import {Check} from 'src/types'
import {ComponentSize} from '@influxdata/clockface'

interface Props {
checks: Check[]
showFirstTimeWidget: boolean
}

const CheckCards: FunctionComponent<Props> = ({checks}) => {
const CheckCards: FunctionComponent<Props> = ({
checks,
showFirstTimeWidget,
}) => {
return (
<>
<ResourceList>
<ResourceList.Body emptyState={<EmptyChecksList />}>
<ResourceList.Body
emptyState={
<EmptyChecksList showFirstTimeWidget={showFirstTimeWidget} />
}
>
{checks.map(check => (
<CheckCard key={check.id} check={check} />
))}
Expand All @@ -27,17 +35,42 @@ const CheckCards: FunctionComponent<Props> = ({checks}) => {
)
}

const EmptyChecksList: FunctionComponent = () => {
interface EmptyProps {
showFirstTimeWidget: boolean
}

const EmptyChecksList: FunctionComponent<EmptyProps> = ({
showFirstTimeWidget,
}) => {
if (showFirstTimeWidget) {
return (
<Panel
gradient={Gradients.GundamPilot}
size={ComponentSize.Large}
className="alerting-first-time"
>
<Panel.Body>
<h1>
Looks like it's your
<br />
first time here
</h1>
<h5>
Welcome to our new Monitoring & Alerting feature!
<br />
Try creating a <strong>Check</strong> to get started
</h5>
</Panel.Body>
</Panel>
)
}

return (
<EmptyState size={ComponentSize.Small} className="alert-column--empty">
<EmptyState.Text
text="A Check is a periodic query that the system performs against your time series data that will generate a status"
text="Looks like you have not created a Check yet LINEBREAK LINEBREAK You will need one to be notified about LINEBREAK any changes in system status"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's up with this LINEBREAK stuff? Could markdown be passed instead? Or the text passed as multiple props?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad you asked! The empty state component is overly strict and ends up shooting itself in the foot in the process. I am planning a small change in the next clockface update that should remove all this funk

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, awesome

highlightWords={['Check']}
/>
<br />
<a href="#" target="_blank">
Documentation
</a>
</EmptyState>
)
}
Expand Down
51 changes: 47 additions & 4 deletions ui/src/alerting/components/ChecksColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import {connect} from 'react-redux'
import {viewableLabels} from 'src/labels/selectors'

// Components
import {Button, IconFont, ComponentColor} from '@influxdata/clockface'
import CheckCards from 'src/alerting/components/CheckCards'
import AlertsColumnHeader from 'src/alerting/components/AlertsColumn'

// Types
import {Check, AppState} from 'src/types'
import {Check, NotificationRuleDraft, AppState} from 'src/types'

interface StateProps {
checks: Check[]
rules: NotificationRuleDraft[]
endpoints: AppState['endpoints']['list']
}

type Props = StateProps & WithRouterProps
Expand All @@ -23,13 +26,46 @@ const ChecksColumn: FunctionComponent<Props> = ({
checks,
router,
params: {orgID},
rules,
endpoints,
}) => {
const handleClick = () => {
router.push(`/orgs/${orgID}/alerting/checks/new`)
}

const tooltipContents = (
<>
A <strong>Check</strong> is a periodic query that the system
<br />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these <br /> have to be here? Feels like an indication that something else could be fixed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I manually placed the line breaks in a way that makes it nice to read rather than relying on left/right padding

performs against your time series data
<br />
that will generate a status
</>
)

const noAlertingResourcesExist =
!checks.length && !rules.length && !endpoints.length

const createButton = (
<Button
color={ComponentColor.Primary}
text="Create"
onClick={handleClick}
testID="create-check"
icon={IconFont.Plus}
/>
)

return (
<AlertsColumnHeader title="Checks" onCreate={handleClick}>
<CheckCards checks={checks} />
<AlertsColumnHeader
title="Checks"
createButton={createButton}
questionMarkTooltipContents={tooltipContents}
>
<CheckCards
checks={checks}
showFirstTimeWidget={noAlertingResourcesExist}
/>
</AlertsColumnHeader>
)
}
Expand All @@ -38,9 +74,16 @@ const mstp = (state: AppState) => {
const {
checks: {list: checks},
labels: {list: labels},
rules: {list: rules},
endpoints,
} = state

return {checks, labels: viewableLabels(labels)}
return {
checks,
labels: viewableLabels(labels),
rules,
endpoints: endpoints.list,
}
}

export default connect<StateProps, {}, {}>(
Expand Down
Loading