Skip to content

Commit 2ab5e8f

Browse files
authored
feat: make selections deterministic (#3837)
1 parent b6f9852 commit 2ab5e8f

File tree

9 files changed

+182
-95
lines changed

9 files changed

+182
-95
lines changed

src/flows/pipes/Visualization/Controls.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import ErrorThresholds from 'src/flows/pipes/Visualization/ErrorThresholds/Error
1717
import {SidebarContext} from 'src/flows/context/sidebar'
1818
import {PipeContext, PipeProvider} from 'src/flows/context/pipe'
1919
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
20+
import ErrorBoundary from 'src/shared/components/ErrorBoundary'
2021

2122
const WrappedViewOptions: FC = () => {
2223
const {data, update, results} = useContext(PipeContext)
@@ -34,14 +35,14 @@ const WrappedViewOptions: FC = () => {
3435
)
3536

3637
return (
37-
<>
38+
<ErrorBoundary>
3839
{isFlagEnabled('flowErrorThresholds') && <ErrorThresholds />}
3940
<ViewOptions
4041
properties={data.properties}
4142
results={results.parsed}
4243
update={updateProperties}
4344
/>
44-
</>
45+
</ErrorBoundary>
4546
)
4647
}
4748

src/flows/pipes/Visualization/ErrorThresholds/ErrorThresholds.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ $text-block-width: 56px;
2121

2222
.add-error-threshold--button {
2323
width: 100%;
24+
margin-bottom: $cf-marg-b;
2425
}

src/flows/pipes/Visualization/ErrorThresholds/ErrorThresholds.tsx

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ import {
1414
TextBlock,
1515
} from '@influxdata/clockface'
1616
import {PipeContext} from 'src/flows/context/pipe'
17-
import ColumnDropdown from 'src/flows/pipes/Visualization/ErrorThresholds/ColumnDropdown'
17+
import ColumnDropdown from 'src/flows/pipes/Visualization/ErrorThresholds/FieldColumnDropdown'
1818
import FunctionDropdown from 'src/flows/pipes/Visualization/ErrorThresholds/FunctionDropdown'
1919
import ThresholdEntryColumn from 'src/flows/pipes/Visualization/ErrorThresholds/ThresholdEntryColumn'
2020
import {event} from 'src/cloud/utils/reporting'
21+
import {ErrorThreshold} from 'src/flows/pipes/Visualization/threshold'
2122
import './ErrorThresholds.scss'
2223

2324
const ErrorThresholds: FC = () => {
@@ -33,8 +34,9 @@ const ErrorThresholds: FC = () => {
3334
errorThresholds: [
3435
...(errorThresholds ?? []),
3536
{
36-
type: 'greater',
37+
type: 'equal',
3738
value: 0,
39+
fieldType: 'not-number',
3840
},
3941
],
4042
})
@@ -64,47 +66,49 @@ const ErrorThresholds: FC = () => {
6466
testID="component-spacer"
6567
stretchToFitWidth
6668
>
67-
{data?.errorThresholds?.map((threshold: any, index: number) => (
68-
<FlexBox
69-
direction={FlexDirection.Row}
70-
margin={ComponentSize.Medium}
71-
stretchToFitWidth
72-
testID="component-spacer"
73-
key={`${threshold.type}_${index}`}
74-
>
75-
<FlexBox.Child grow={3} testID="component-spacer--flex-child">
76-
<FlexBox
77-
stretchToFitWidth
78-
className="error-threshold-flex--margin"
79-
>
80-
<TextBlock
81-
testID="when-value-text-block"
82-
text={index === 0 ? 'When' : 'And'}
83-
className="error-threshold--text-block"
84-
/>
85-
<ColumnDropdown threshold={threshold} index={index} />
86-
</FlexBox>
87-
<FlexBox
88-
stretchToFitWidth
89-
className="error-threshold-flex--margin"
90-
>
91-
<TextBlock
92-
testID="is-value-text-block"
93-
text="is"
94-
className="error-threshold--text-block"
95-
/>
96-
<FunctionDropdown threshold={threshold} index={index} />
97-
</FlexBox>
98-
<ThresholdEntryColumn threshold={threshold} index={index} />
99-
</FlexBox.Child>
100-
<Button
101-
icon={IconFont.Trash_New}
102-
size={ComponentSize.Small}
103-
onClick={() => handleRemoveThreshold(index)}
104-
color={ComponentColor.Tertiary}
105-
/>
106-
</FlexBox>
107-
))}
69+
{data?.errorThresholds?.map(
70+
(threshold: ErrorThreshold, index: number) => (
71+
<FlexBox
72+
direction={FlexDirection.Row}
73+
margin={ComponentSize.Medium}
74+
stretchToFitWidth
75+
testID="component-spacer"
76+
key={`${threshold.type}_${index}`}
77+
>
78+
<FlexBox.Child grow={3} testID="component-spacer--flex-child">
79+
<FlexBox
80+
stretchToFitWidth
81+
className="error-threshold-flex--margin"
82+
>
83+
<TextBlock
84+
testID="when-value-text-block"
85+
text={index === 0 ? 'When' : 'And'}
86+
className="error-threshold--text-block"
87+
/>
88+
<ColumnDropdown threshold={threshold} index={index} />
89+
</FlexBox>
90+
<FlexBox
91+
stretchToFitWidth
92+
className="error-threshold-flex--margin"
93+
>
94+
<TextBlock
95+
testID="is-value-text-block"
96+
text="is"
97+
className="error-threshold--text-block"
98+
/>
99+
<FunctionDropdown threshold={threshold} index={index} />
100+
</FlexBox>
101+
<ThresholdEntryColumn threshold={threshold} index={index} />
102+
</FlexBox.Child>
103+
<Button
104+
icon={IconFont.Trash_New}
105+
size={ComponentSize.Small}
106+
onClick={() => handleRemoveThreshold(index)}
107+
color={ComponentColor.Tertiary}
108+
/>
109+
</FlexBox>
110+
)
111+
)}
108112
</FlexBox>
109113
<FlexBox
110114
direction={FlexDirection.Row}

src/flows/pipes/Visualization/ErrorThresholds/ColumnDropdown.tsx renamed to src/flows/pipes/Visualization/ErrorThresholds/FieldColumnDropdown.tsx

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import React, {FC, useCallback, useContext, useMemo} from 'react'
55
import {ComponentSize, Dropdown} from '@influxdata/clockface'
66
import {PipeContext} from 'src/flows/context/pipe'
77
import {event} from 'src/cloud/utils/reporting'
8-
import {Threshold} from 'src/flows/pipes/Visualization/threshold'
8+
import {ErrorThreshold} from 'src/flows/pipes/Visualization/threshold'
99

1010
type Props = {
11-
threshold: Threshold
11+
threshold: ErrorThreshold
1212
index: number
1313
}
1414

15-
const ColumnDropdown: FC<Props> = ({threshold, index}) => {
15+
const FieldColumnDropdown: FC<Props> = ({threshold, index}) => {
1616
const {data, update, results} = useContext(PipeContext)
1717

1818
const fields = Array.from(
@@ -33,9 +33,43 @@ const ColumnDropdown: FC<Props> = ({threshold, index}) => {
3333
threshold.field = column
3434
}
3535

36+
const values = Object.values(results.parsed.table.columns).filter(c => {
37+
return c.name === '_value'
38+
})
39+
40+
const fields = (results.parsed.table.columns['_field']
41+
.data as any).reduce((acc, curr, index) => {
42+
const type = values.find(d => {
43+
return d.data[index] !== undefined
44+
})?.type
45+
if (!acc[curr]) {
46+
acc[curr] = {}
47+
}
48+
acc[curr][type] = true
49+
return acc
50+
}, {})
51+
52+
const fieldTypes = Object.keys(fields[threshold?.field] ?? {})
53+
let fieldType: 'not-number' | 'number' = 'not-number'
54+
if (fieldTypes.length === 1 && fieldTypes[0] === 'number') {
55+
fieldType = 'number'
56+
}
57+
58+
threshold.fieldType = fieldType
59+
60+
// We want to invalidate the previous type selection if the
61+
// fieldType is not a number, and the selected type is not equality based
62+
if (
63+
threshold.fieldType !== 'number' &&
64+
threshold.type !== 'equal' &&
65+
threshold.type !== 'not-equal'
66+
) {
67+
threshold.type = 'equal'
68+
}
69+
3670
update({errorThresholds})
3771
},
38-
[errorThresholds, update]
72+
[results.parsed.table.columns, errorThresholds, update]
3973
)
4074

4175
const menuItems = fields.map(key => (
@@ -66,4 +100,4 @@ const ColumnDropdown: FC<Props> = ({threshold, index}) => {
66100
return <Dropdown menu={menu} button={menuButton} />
67101
}
68102

69-
export default ColumnDropdown
103+
export default FieldColumnDropdown

src/flows/pipes/Visualization/ErrorThresholds/FunctionDropdown.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import {PipeContext} from 'src/flows/context/pipe'
77
import {event} from 'src/cloud/utils/reporting'
88
import {
99
COMMON_THRESHOLD_TYPES,
10-
Threshold,
10+
EQUALITY_THRESHOLD_TYPES,
11+
ErrorThreshold,
1112
ThresholdFormat,
1213
} from 'src/flows/pipes/Visualization/threshold'
1314

1415
type Props = {
15-
threshold: Threshold
16+
threshold: ErrorThreshold
1617
index: number
1718
}
1819
const FunctionDropdown: FC<Props> = ({threshold, index}) => {
@@ -51,19 +52,22 @@ const FunctionDropdown: FC<Props> = ({threshold, index}) => {
5152
[errorThresholds, update]
5253
)
5354

54-
const menuItems = Object.entries(COMMON_THRESHOLD_TYPES).map(
55-
([key, value]) => (
56-
<Dropdown.Item
57-
key={key}
58-
value={key}
59-
onClick={type => setThresholdType(type, index)}
60-
selected={key === threshold?.type}
61-
title={value.name}
62-
>
63-
{value?.name}
64-
</Dropdown.Item>
65-
)
66-
)
55+
const THRESHOLD_TYPES =
56+
threshold?.fieldType === 'number'
57+
? COMMON_THRESHOLD_TYPES
58+
: EQUALITY_THRESHOLD_TYPES
59+
60+
const menuItems = Object.entries(THRESHOLD_TYPES).map(([key, value]) => (
61+
<Dropdown.Item
62+
key={key}
63+
value={key}
64+
onClick={type => setThresholdType(type, index)}
65+
selected={key === threshold?.type}
66+
title={value.name}
67+
>
68+
{value?.name}
69+
</Dropdown.Item>
70+
))
6771
const menu = onCollapse => (
6872
<Dropdown.Menu onCollapse={onCollapse}>{menuItems}</Dropdown.Menu>
6973
)

src/flows/pipes/Visualization/ErrorThresholds/ThresholdEntryColumn.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import {PipeContext} from 'src/flows/context/pipe'
1414
import {event} from 'src/cloud/utils/reporting'
1515
import {
1616
COMMON_THRESHOLD_TYPES,
17-
Threshold,
17+
ErrorThreshold,
1818
ThresholdFormat,
1919
} from 'src/flows/pipes/Visualization/threshold'
2020
import './ErrorThresholds.scss'
2121

2222
type Props = {
23-
threshold: Threshold
23+
threshold: ErrorThreshold
2424
index: number
2525
}
2626

@@ -57,9 +57,14 @@ const ThresholdEntryColumn: FC<Props> = ({threshold, index}) => {
5757
) => {
5858
event('Alert Panel (Notebooks) - Threshold Value Entered')
5959
const threshold = errorThresholds.find((_, i) => index === i)
60+
if (!threshold) {
61+
return
62+
}
6063

61-
if (threshold) {
64+
if (threshold.fieldType === 'number') {
6265
threshold.value = Number(changeEvent.target.value)
66+
} else {
67+
threshold.value = changeEvent.target.value
6368
}
6469

6570
update({errorThresholds})
@@ -83,7 +88,7 @@ const ThresholdEntryColumn: FC<Props> = ({threshold, index}) => {
8388
<>
8489
<Input
8590
name="interval"
86-
type={InputType.Text}
91+
type={InputType.Number}
8792
placeholder="min"
8893
value={threshold.min}
8994
onChange={event => updateMin(event, index)}
@@ -96,7 +101,7 @@ const ThresholdEntryColumn: FC<Props> = ({threshold, index}) => {
96101
/>
97102
<Input
98103
name="interval"
99-
type={InputType.Text}
104+
type={InputType.Number}
100105
placeholder="max"
101106
value={threshold.max}
102107
onChange={event => updateMax(event, index)}

src/flows/pipes/Visualization/threshold.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ export type Threshold = {
1414
deadmanStopValue: string
1515
}
1616

17+
export interface ErrorThreshold extends Threshold {
18+
fieldType: string
19+
}
20+
1721
export const COMMON_THRESHOLD_TYPES = {
1822
greater: {
1923
name: 'greater than',
@@ -59,6 +63,19 @@ export const COMMON_THRESHOLD_TYPES = {
5963
},
6064
}
6165

66+
export const EQUALITY_THRESHOLD_TYPES = {
67+
equal: {
68+
name: 'equal to',
69+
format: ThresholdFormat.Value,
70+
condition: data => `(r) => (r["${data.field}"] == ${data.value})`,
71+
},
72+
'not-equal': {
73+
name: 'not equal to',
74+
format: ThresholdFormat.Value,
75+
condition: data => `(r) => (r["${data.field}"] != ${data.value})`,
76+
},
77+
}
78+
6279
export const deadmanType = 'missing-for-longer-than'
6380

6481
export const THRESHOLD_TYPES = {

0 commit comments

Comments
 (0)