refactor(ui): update check builder design (#15040)

* refactor(ui): move check message to its own card

* refactor(ui): ensure builder cards fill width of overlay

* refactor(ui): make conditions boxes fill width of parent

* refactor(ui): allow check properties card to grow

* refactor(ui): remove matching rules card

* chore(ui): update changelog
pull/15044/head
alexpaxton 2019-09-06 16:30:39 -07:00 committed by GitHub
parent c80eb929d0
commit f2aff59a75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 363 additions and 284 deletions

View File

@ -3,6 +3,7 @@
### Features
### UI Improvements
1. [15040](https://github.com/influxdata/influxdb/pull/15040): Redesign check builder UI to fill the screen and make more room for composing message templates
1. [14990](https://github.com/influxdata/influxdb/pull/14990): Move Tokens tab from Settings to Load Data page
1. [14990](https://github.com/influxdata/influxdb/pull/14990): Expose all Settings tabs in navigation menu

View File

@ -3,7 +3,19 @@
------------------------------------------------------------------------------
*/
.alert-builder {
padding: 0 $ix-marg-c;
background-color: $g2-kevlar;
}
.alert-builder--controls {
border-bottom: 0;
padding-right: $ix-marg-c;
}
.alert-builder--card {
margin-bottom: $ix-marg-c;
.builder-card--contents {
min-height: 100%;
padding: 16px;
@ -11,6 +23,16 @@
.builder-card--header {
justify-content: center;
}
&.alert-builder--meta-card {
flex: 1 0 320px !important;
}
&.alert-builder--message-card {
flex: 3 0 480px !important;
}
&.alert-builder--conditions-card {
flex: 2 0 510px !important;
}
}
.cf-empty-state.alert-builder--card__empty {
@ -19,18 +41,35 @@
justify-content: center;
}
.alert-builder--message-template {
.cf-text-area--container.cf-input-md {
height: auto;
}
.alert-builder--message-template.cf-text-area--container.cf-input-md {
height: auto;
textarea {
height: 90px;
height: 120px;
font-family: $code-font;
}
}
.alert-builder--message-help {
padding: 0 $ix-marg-c;
p {
font-size: 13px;
font-weight: 500;
}
code {
background-color: $g2-kevlar;
color: $c-potassium;
padding: 2px 4px;
border-radius: 3px;
user-select: text;
}
}
.alert-builder--check-type-selector {
margin: $ix-marg-c;
margin-bottom: $ix-marg-c;
}
.alert-builder--tag-row {

View File

@ -3,47 +3,19 @@ import React, {FC} from 'react'
// Components
import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar'
import BuilderCard from 'src/timeMachine/components/builderCard/BuilderCard'
import CheckMetaCard from 'src/alerting/components/builder/CheckMetaCard'
import CheckMessageCard from 'src/alerting/components/builder/CheckMessageCard'
import CheckConditionsCard from 'src/alerting/components/builder/CheckConditionsCard'
import CheckMatchingRulesCard from 'src/alerting/components/builder/CheckMatchingRulesCard'
const AlertBuilder: FC = () => {
return (
<div className="query-builder" data-testid="query-builder">
<div className="query-builder alert-builder" data-testid="query-builder">
<div className="query-builder--cards">
<FancyScrollbar>
<div className="builder-card--list">
<BuilderCard
testID="builder-meta"
widthPixels={340}
className="alert-builder--card"
>
<BuilderCard.Header title="Properties" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<CheckMetaCard />
</BuilderCard.Body>
</BuilderCard>
<BuilderCard
testID="builder-conditions"
widthPixels={510}
className="alert-builder--card"
>
<BuilderCard.Header title="Conditions" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<CheckConditionsCard />
</BuilderCard.Body>
</BuilderCard>
<BuilderCard
testID="builder-matching-rules"
widthPixels={420}
className="alert-builder--card"
>
<BuilderCard.Header title="Matching Notification Rules" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<CheckMatchingRulesCard />
</BuilderCard.Body>
</BuilderCard>
<div className="builder-card--list alert-builder--list">
<CheckMetaCard />
<CheckMessageCard />
<CheckConditionsCard />
</div>
</FancyScrollbar>
</div>

View File

@ -13,6 +13,7 @@ import {
} from '@influxdata/clockface'
import ThresholdConditions from 'src/alerting/components/builder/ThresholdConditions'
import DeadmanConditions from 'src/alerting/components/builder/DeadmanConditions'
import BuilderCard from 'src/timeMachine/components/builderCard/BuilderCard'
// Actions & Selectors
import {changeCheckType} from 'src/timeMachine/actions'
@ -33,50 +34,55 @@ type Props = DispatchProps & StateProps
const CheckConditionsCard: FC<Props> = ({check, changeCheckType}) => {
return (
<>
<FlexBox
direction={FlexDirection.Row}
alignItems={AlignItems.Center}
stretchToFitWidth={true}
justifyContent={JustifyContent.Center}
margin={ComponentSize.Medium}
className="alert-builder--check-type-selector"
>
<Radio>
<Radio.Button
key="threshold"
id="threshold"
titleText="threshold"
value="threshold"
active={check.type === 'threshold'}
onClick={changeCheckType}
>
Threshold
</Radio.Button>
<Radio.Button
key="deadman"
id="deadman"
titleText="deadman"
value="deadman"
active={check.type === 'deadman'}
onClick={changeCheckType}
>
Deadman
</Radio.Button>
</Radio>
</FlexBox>
<FlexBox
direction={FlexDirection.Column}
alignItems={AlignItems.Stretch}
margin={ComponentSize.Medium}
>
{check.type === 'deadman' ? (
<DeadmanConditions check={check} />
) : (
<ThresholdConditions check={check} />
)}
</FlexBox>
</>
<BuilderCard
testID="builder-conditions"
className="alert-builder--card alert-builder--conditions-card"
>
<BuilderCard.Header title="Conditions" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<FlexBox
direction={FlexDirection.Row}
alignItems={AlignItems.Center}
stretchToFitWidth={true}
justifyContent={JustifyContent.Center}
className="alert-builder--check-type-selector"
>
<Radio>
<Radio.Button
key="threshold"
id="threshold"
titleText="threshold"
value="threshold"
active={check.type === 'threshold'}
onClick={changeCheckType}
>
Threshold
</Radio.Button>
<Radio.Button
key="deadman"
id="deadman"
titleText="deadman"
value="deadman"
active={check.type === 'deadman'}
onClick={changeCheckType}
>
Deadman
</Radio.Button>
</Radio>
</FlexBox>
<FlexBox
direction={FlexDirection.Column}
alignItems={AlignItems.Stretch}
margin={ComponentSize.Medium}
>
{check.type === 'deadman' ? (
<DeadmanConditions check={check} />
) : (
<ThresholdConditions check={check} />
)}
</FlexBox>
</BuilderCard.Body>
</BuilderCard>
)
}

View File

@ -5,8 +5,7 @@ import {get} from 'lodash'
// Components
import MatchingRuleCard from 'src/alerting/components/builder/MatchingRuleCard'
import {SpinnerContainer} from '@influxdata/clockface'
import {TechnoSpinner} from '@influxdata/clockface'
import {SpinnerContainer, TechnoSpinner} from '@influxdata/clockface'
// Actions
import {getActiveTimeMachine} from 'src/timeMachine/selectors'

View File

@ -0,0 +1,98 @@
// Libraries
import React, {FC} from 'react'
import {connect} from 'react-redux'
// Components
import {
ComponentSize,
TextArea,
AutoComplete,
Wrap,
} from '@influxdata/clockface'
import BuilderCard from 'src/timeMachine/components/builderCard/BuilderCard'
// Actions & Selectors
import {updateTimeMachineCheck} from 'src/timeMachine/actions'
import {getActiveTimeMachine} from 'src/timeMachine/selectors'
// Types
import {Check, AppState} from 'src/types'
interface DispatchProps {
onUpdateTimeMachineCheck: typeof updateTimeMachineCheck
}
interface StateProps {
check: Partial<Check>
}
type Props = DispatchProps & StateProps
const CheckMessageCard: FC<Props> = ({check, onUpdateTimeMachineCheck}) => {
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
onUpdateTimeMachineCheck({[e.target.name]: e.target.value})
}
return (
<BuilderCard
testID="builder-message"
className="alert-builder--card alert-builder--message-card"
>
<BuilderCard.Header title="Status Message Template" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<TextArea
className="alert-builder--message-template"
autoFocus={false}
autocomplete={AutoComplete.Off}
form=""
maxLength={500}
minLength={5}
name="statusMessageTemplate"
onChange={handleChange}
readOnly={false}
required={false}
size={ComponentSize.Medium}
spellCheck={false}
testID="status-message-textarea"
value={check.statusMessageTemplate}
wrap={Wrap.Soft}
placeholder="This template what this Check will use to write status messages"
/>
<div className="alert-builder--message-help">
<p>
You can use any columns from your query as well as the following:
</p>
<p>
<code>{'${r._check_name}'}</code> The name of this check
</p>
<p>
<code>{'${r._level}'}</code> Indicates the level of the check
</p>
<p>
<code>{'${string(v: r.numericColumn)}'}</code> Functions can be used{' '}
as well
</p>
</div>
</BuilderCard.Body>
</BuilderCard>
)
}
const mstp = (state: AppState): StateProps => {
const {
alerting: {check},
} = getActiveTimeMachine(state)
return {check}
}
const mdtp: DispatchProps = {
onUpdateTimeMachineCheck: updateTimeMachineCheck,
}
export default connect<StateProps, DispatchProps, {}>(
mstp,
mdtp
)(CheckMessageCard)

View File

@ -3,19 +3,12 @@ import React, {FC} from 'react'
import {connect} from 'react-redux'
// Components
import {
Form,
ComponentSize,
TextArea,
AutoComplete,
Wrap,
ComponentColor,
Grid,
} from '@influxdata/clockface'
import {Form, ComponentSize, ComponentColor, Grid} from '@influxdata/clockface'
import {Input} from '@influxdata/clockface'
import DashedButton from 'src/shared/components/dashed_button/DashedButton'
import CheckTagRow from 'src/alerting/components/builder/CheckTagRow'
import DurationSelector from 'src/timeMachine/components/DurationSelector'
import BuilderCard from 'src/timeMachine/components/builderCard/BuilderCard'
// Actions & Selectors
import {updateTimeMachineCheck} from 'src/timeMachine/actions'
@ -68,78 +61,65 @@ const CheckMetaCard: FC<Props> = ({
}
return (
<>
<Form.Element label="Name">
<Input
autoFocus={true}
name="name"
onChange={handleChange}
placeholder="Name this check"
size={ComponentSize.Small}
value={check.name}
/>
</Form.Element>
<Form.Element
label="Status Message Template"
className="alert-builder--message-template"
>
<TextArea
autoFocus={false}
autocomplete={AutoComplete.Off}
form=""
maxLength={500}
minLength={5}
name="statusMessageTemplate"
onChange={handleChange}
readOnly={false}
required={false}
size={ComponentSize.Medium}
spellCheck={false}
testID="status-message-textarea"
value={check.statusMessageTemplate}
wrap={Wrap.Soft}
/>
</Form.Element>
<Grid>
<Grid.Row>
<Grid.Column widthSM={6}>
<Form.Element label="Schedule Every">
<DurationSelector
selectedDuration={check.every}
durations={CHECK_EVERY_OPTIONS}
onSelectDuration={onSelectCheckEvery}
/>
</Form.Element>
</Grid.Column>
<Grid.Column widthSM={6}>
<Form.Element label="Offset">
<DurationSelector
selectedDuration={check.offset}
durations={CHECK_OFFSET_OPTIONS}
onSelectDuration={offset => onUpdateTimeMachineCheck({offset})}
/>
</Form.Element>
</Grid.Column>
</Grid.Row>
</Grid>
<Form.Label label="Tags" />
{check.tags &&
check.tags.map((t, i) => (
<CheckTagRow
key={i}
index={i}
tagSet={t}
handleChangeTagRow={handleChangeTagRow}
handleRemoveTagRow={handleRemoveTagRow}
<BuilderCard
testID="builder-meta"
className="alert-builder--card alert-builder--meta-card"
>
<BuilderCard.Header title="Properties" />
<BuilderCard.Body addPadding={true} autoHideScrollbars={true}>
<Form.Element label="Name">
<Input
autoFocus={true}
name="name"
onChange={handleChange}
placeholder="Name this check"
size={ComponentSize.Small}
value={check.name}
/>
))}
<DashedButton
text="+ Tag"
onClick={addTagsRow}
color={ComponentColor.Primary}
size={ComponentSize.Small}
/>
</>
</Form.Element>
<Grid>
<Grid.Row>
<Grid.Column widthSM={6}>
<Form.Element label="Schedule Every">
<DurationSelector
selectedDuration={check.every}
durations={CHECK_EVERY_OPTIONS}
onSelectDuration={onSelectCheckEvery}
/>
</Form.Element>
</Grid.Column>
<Grid.Column widthSM={6}>
<Form.Element label="Offset">
<DurationSelector
selectedDuration={check.offset}
durations={CHECK_OFFSET_OPTIONS}
onSelectDuration={offset =>
onUpdateTimeMachineCheck({offset})
}
/>
</Form.Element>
</Grid.Column>
</Grid.Row>
</Grid>
<Form.Label label="Tags" />
{check.tags &&
check.tags.map((t, i) => (
<CheckTagRow
key={i}
index={i}
tagSet={t}
handleChangeTagRow={handleChangeTagRow}
handleRemoveTagRow={handleRemoveTagRow}
/>
))}
<DashedButton
text="+ Tag"
onClick={addTagsRow}
color={ComponentColor.Primary}
size={ComponentSize.Small}
/>
</BuilderCard.Body>
</BuilderCard>
)
}

View File

@ -12,6 +12,7 @@ import {
InputType,
Input,
FlexDirection,
InfluxColors,
} from '@influxdata/clockface'
import CheckLevelsDropdown from 'src/alerting/components/builder/CheckLevelsDropdown'
@ -42,82 +43,73 @@ const DeadmanConditions: FC<Props> = ({
onUpdateTimeMachineCheck({level})
}
return (
<div
style={{
width: '475px',
}}
>
<Panel backgroundColor="#292933" testID="panel">
<PanelBody testID="panel--body">
<Panel backgroundColor={InfluxColors.Castle} testID="panel">
<PanelBody testID="panel--body">
<FlexBox
direction={FlexDirection.Column}
margin={ComponentSize.Small}
testID="component-spacer"
>
<FlexBox
direction={FlexDirection.Column}
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<FlexBox.Child testID="component-spacer--flex-child">
<TextBlock
testID="when-value-text-block"
text="When values are not reporting"
/>
</FlexBox.Child>
</FlexBox>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<TextBlock testID="when-value-text-block" text="for" />
<FlexBox.Child testID="component-spacer--flex-child">
<Input
onChange={handleChange}
name="timeSince"
testID="input-field"
type={InputType.Text}
value={timeSince}
/>
</FlexBox.Child>
<TextBlock
testID="set-status-to-text-block"
text="set status to"
/>
<FlexBox.Child testID="component-spacer--flex-child">
<CheckLevelsDropdown
selectedLevel={level}
onClickLevel={handleChangeLevel}
/>
</FlexBox.Child>
</FlexBox>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<FlexBox.Child testID="component-spacer--flex-child">
<TextBlock
testID="when-value-text-block"
text="And stop checking after"
text="When values are not reporting"
/>
<FlexBox.Child testID="component-spacer--flex-child">
<Input
onChange={handleChange}
name="staleTime"
testID="input-field"
type={InputType.Text}
value={staleTime}
/>
</FlexBox.Child>
</FlexBox>
</FlexBox.Child>
</FlexBox>
</PanelBody>
</Panel>
</div>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<TextBlock testID="when-value-text-block" text="for" />
<FlexBox.Child testID="component-spacer--flex-child">
<Input
onChange={handleChange}
name="timeSince"
testID="input-field"
type={InputType.Text}
value={timeSince}
/>
</FlexBox.Child>
<TextBlock testID="set-status-to-text-block" text="set status to" />
<FlexBox.Child testID="component-spacer--flex-child">
<CheckLevelsDropdown
selectedLevel={level}
onClickLevel={handleChangeLevel}
/>
</FlexBox.Child>
</FlexBox>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<TextBlock
testID="when-value-text-block"
text="And stop checking after"
/>
<FlexBox.Child testID="component-spacer--flex-child">
<Input
onChange={handleChange}
name="staleTime"
testID="input-field"
type={InputType.Text}
value={staleTime}
/>
</FlexBox.Child>
</FlexBox>
</FlexBox>
</PanelBody>
</Panel>
)
}

View File

@ -13,6 +13,7 @@ import {
ButtonType,
FlexDirection,
ComponentColor,
InfluxColors,
} from '@influxdata/clockface'
// Types
@ -59,61 +60,52 @@ const ThresholdStatement: FC<Props> = ({
}
return (
<div
style={{
width: '475px',
}}
>
<Panel backgroundColor="#292933" testID="panel">
<DismissButton
color={ComponentColor.Default}
onClick={removeLevel}
testID="dismiss-button"
type={ButtonType.Button}
/>
<PanelBody testID="panel--body">
<Panel backgroundColor={InfluxColors.Castle} testID="panel">
<DismissButton
color={ComponentColor.Default}
onClick={removeLevel}
testID="dismiss-button"
type={ButtonType.Button}
/>
<PanelBody testID="panel--body">
<FlexBox
direction={FlexDirection.Column}
margin={ComponentSize.Small}
testID="component-spacer"
>
<FlexBox
direction={FlexDirection.Column}
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
<TextBlock testID="when-value-text-block" text="When value" />
<FlexBox.Child grow={2} testID="component-spacer--flex-child">
<SelectDropdown
options={Object.keys(dropdownOptions)}
selectedOption={selectedOption}
onSelect={onChangeThresholdType}
testID="select-option-dropdown"
/>
</FlexBox.Child>
</FlexBox>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
{children}
<TextBlock
testID="set-status-to-text-block"
text="set status to"
<TextBlock testID="when-value-text-block" text="When value" />
<FlexBox.Child grow={2} testID="component-spacer--flex-child">
<SelectDropdown
options={Object.keys(dropdownOptions)}
selectedOption={selectedOption}
onSelect={onChangeThresholdType}
testID="select-option-dropdown"
/>
<TextBlock
backgroundColor={levelColor}
testID="threshold-level-text-block"
text={threshold.level}
/>
</FlexBox>
</FlexBox.Child>
</FlexBox>
</PanelBody>
</Panel>
</div>
<FlexBox
direction={FlexDirection.Row}
margin={ComponentSize.Small}
stretchToFitWidth
testID="component-spacer"
>
{children}
<TextBlock testID="set-status-to-text-block" text="set status to" />
<TextBlock
backgroundColor={levelColor}
testID="threshold-level-text-block"
text={threshold.level}
/>
</FlexBox>
</FlexBox>
</PanelBody>
</Panel>
)
}

View File

@ -14,7 +14,7 @@ import HelpButton from 'src/alerting/components/builder/HelpButton'
const TimeMachineAlerting: FunctionComponent = () => {
return (
<div className="time-machine-queries">
<div className="time-machine-queries--controls">
<div className="time-machine-queries--controls alert-builder--controls">
<div className="time-machine--editor-title">Configure a Check</div>
<div className="time-machine-queries--buttons">
<FlexBox