Skip to content

Commit 3578eb2

Browse files
authored
feat(aci): add eventUniqueUserFrequency and percentSessions data condition nodes (#91826)
uses the same logic as the eventFrequency data condition node (#91786) to implement branching https://github.com/user-attachments/assets/e336ac2c-228a-4020-88a2-e7c6a9e17ebb
1 parent fa8b95c commit 3578eb2

File tree

7 files changed

+215
-68
lines changed

7 files changed

+215
-68
lines changed

static/app/types/workflowEngine/dataConditions.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export enum DataConditionType {
5757

5858
// frequency types for UI only
5959
EVENT_FREQUENCY = 'event_frequency',
60+
EVENT_UNIQUE_USER_FREQUENCY = 'event_unique_user_frequency',
61+
PERCENT_SESSIONS = 'percent_sessions',
6062
}
6163

6264
export enum DataConditionGroupLogicType {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import AutomationBuilderNumberField from 'sentry/components/workflowEngine/form/automationBuilderNumberField';
2+
import AutomationBuilderSelectField from 'sentry/components/workflowEngine/form/automationBuilderSelectField';
3+
import {tct} from 'sentry/locale';
4+
import {
5+
COMPARISON_INTERVAL_CHOICES,
6+
INTERVAL_CHOICES,
7+
} from 'sentry/views/automations/components/actionFilters/constants';
8+
import {useDataConditionNodeContext} from 'sentry/views/automations/components/dataConditionNodes';
9+
10+
export function CountBranch() {
11+
return tct('more than [value] [interval]', {
12+
value: <ValueField />,
13+
interval: <IntervalField />,
14+
});
15+
}
16+
17+
export function PercentBranch() {
18+
return tct('[value] higher [interval] compared to [comparison_interval]', {
19+
value: <ValueField />,
20+
interval: <IntervalField />,
21+
comparison_interval: <ComparisonIntervalField />,
22+
});
23+
}
24+
25+
function ValueField() {
26+
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
27+
return (
28+
<AutomationBuilderNumberField
29+
name={`${condition_id}.comparison.value`}
30+
value={condition.comparison.value}
31+
min={1}
32+
step={1}
33+
onChange={(value: string) => {
34+
onUpdate({
35+
value,
36+
});
37+
}}
38+
/>
39+
);
40+
}
41+
42+
function IntervalField() {
43+
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
44+
return (
45+
<AutomationBuilderSelectField
46+
name={`${condition_id}.comparison.interval`}
47+
value={condition.comparison.interval}
48+
options={INTERVAL_CHOICES}
49+
onChange={(value: string) => {
50+
onUpdate({
51+
interval: value,
52+
});
53+
}}
54+
/>
55+
);
56+
}
57+
58+
function ComparisonIntervalField() {
59+
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
60+
return (
61+
<AutomationBuilderSelectField
62+
name={`${condition_id}.comparison.comparison_interval`}
63+
value={condition.comparison.comparison_interval}
64+
options={COMPARISON_INTERVAL_CHOICES}
65+
onChange={(value: string) => {
66+
onUpdate({
67+
comparison_interval: value,
68+
});
69+
}}
70+
/>
71+
);
72+
}

static/app/views/automations/components/actionFilters/constants.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export const FILTER_DATA_CONDITION_TYPES = [
2222
DataConditionType.TAGGED_EVENT,
2323
DataConditionType.LEVEL,
2424
DataConditionType.EVENT_FREQUENCY,
25+
DataConditionType.EVENT_UNIQUE_USER_FREQUENCY,
26+
DataConditionType.PERCENT_SESSIONS,
2527
];
2628

2729
export enum MatchType {
Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import AutomationBuilderNumberField from 'sentry/components/workflowEngine/form/automationBuilderNumberField';
21
import AutomationBuilderSelectField from 'sentry/components/workflowEngine/form/automationBuilderSelectField';
32
import {tct} from 'sentry/locale';
43
import {DataConditionType} from 'sentry/types/workflowEngine/dataConditions';
54
import {
6-
COMPARISON_INTERVAL_CHOICES,
7-
INTERVAL_CHOICES,
8-
} from 'sentry/views/automations/components/actionFilters/constants';
5+
CountBranch,
6+
PercentBranch,
7+
} from 'sentry/views/automations/components/actionFilters/comparisonBranches';
98
import {useDataConditionNodeContext} from 'sentry/views/automations/components/dataConditionNodes';
109

1110
export default function EventFrequencyNode() {
@@ -44,67 +43,3 @@ function ComparisonTypeField() {
4443
/>
4544
);
4645
}
47-
48-
function CountBranch() {
49-
return tct('more than [value] [interval]', {
50-
value: <ValueField />,
51-
interval: <IntervalField />,
52-
});
53-
}
54-
55-
function PercentBranch() {
56-
return tct('[value] higher [interval] compared to [comparison_interval]', {
57-
value: <ValueField />,
58-
interval: <IntervalField />,
59-
comparison_interval: <ComparisonIntervalField />,
60-
});
61-
}
62-
63-
function ValueField() {
64-
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
65-
return (
66-
<AutomationBuilderNumberField
67-
name={`${condition_id}.comparison.value`}
68-
value={condition.comparison.value}
69-
min={1}
70-
step={1}
71-
onChange={(value: string) => {
72-
onUpdate({
73-
value,
74-
});
75-
}}
76-
/>
77-
);
78-
}
79-
80-
function IntervalField() {
81-
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
82-
return (
83-
<AutomationBuilderSelectField
84-
name={`${condition_id}.comparison.interval`}
85-
value={condition.comparison.interval}
86-
options={INTERVAL_CHOICES}
87-
onChange={(value: string) => {
88-
onUpdate({
89-
interval: value,
90-
});
91-
}}
92-
/>
93-
);
94-
}
95-
96-
function ComparisonIntervalField() {
97-
const {condition, condition_id, onUpdate} = useDataConditionNodeContext();
98-
return (
99-
<AutomationBuilderSelectField
100-
name={`${condition_id}.comparison.comparison_interval`}
101-
value={condition.comparison.comparison_interval}
102-
options={COMPARISON_INTERVAL_CHOICES}
103-
onChange={(value: string) => {
104-
onUpdate({
105-
comparison_interval: value,
106-
});
107-
}}
108-
/>
109-
);
110-
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import AutomationBuilderSelectField from 'sentry/components/workflowEngine/form/automationBuilderSelectField';
2+
import {tct} from 'sentry/locale';
3+
import {DataConditionType} from 'sentry/types/workflowEngine/dataConditions';
4+
import {
5+
CountBranch,
6+
PercentBranch,
7+
} from 'sentry/views/automations/components/actionFilters/comparisonBranches';
8+
import {useDataConditionNodeContext} from 'sentry/views/automations/components/dataConditionNodes';
9+
10+
export default function EventUniqueUserFrequencyNode() {
11+
return tct('Number of users affected by an issue is [select]', {
12+
select: <ComparisonTypeField />,
13+
});
14+
}
15+
16+
function ComparisonTypeField() {
17+
const {condition, condition_id, onUpdateType} = useDataConditionNodeContext();
18+
19+
if (condition.comparison_type === DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_COUNT) {
20+
return <CountBranch />;
21+
}
22+
if (
23+
condition.comparison_type === DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_PERCENT
24+
) {
25+
return <PercentBranch />;
26+
}
27+
28+
return (
29+
<AutomationBuilderSelectField
30+
name={`${condition_id}.comparison_type`}
31+
value={condition.comparison_type}
32+
options={[
33+
{
34+
label: 'more than...',
35+
value: DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_COUNT,
36+
},
37+
{
38+
label: 'relatively higher than...',
39+
value: DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_PERCENT,
40+
},
41+
]}
42+
onChange={(value: DataConditionType) => {
43+
onUpdateType(value);
44+
}}
45+
/>
46+
);
47+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import AutomationBuilderSelectField from 'sentry/components/workflowEngine/form/automationBuilderSelectField';
2+
import {tct} from 'sentry/locale';
3+
import {DataConditionType} from 'sentry/types/workflowEngine/dataConditions';
4+
import {
5+
CountBranch,
6+
PercentBranch,
7+
} from 'sentry/views/automations/components/actionFilters/comparisonBranches';
8+
import {useDataConditionNodeContext} from 'sentry/views/automations/components/dataConditionNodes';
9+
10+
export default function PercentSessionsNode() {
11+
return tct('Percentage of sessions affected by an issue is [select]', {
12+
select: <ComparisonTypeField />,
13+
});
14+
}
15+
16+
function ComparisonTypeField() {
17+
const {condition, condition_id, onUpdateType} = useDataConditionNodeContext();
18+
19+
if (condition.comparison_type === DataConditionType.PERCENT_SESSIONS_COUNT) {
20+
return <CountBranch />;
21+
}
22+
if (condition.comparison_type === DataConditionType.PERCENT_SESSIONS_PERCENT) {
23+
return <PercentBranch />;
24+
}
25+
26+
return (
27+
<AutomationBuilderSelectField
28+
name={`${condition_id}.comparison_type`}
29+
value={condition.comparison_type}
30+
options={[
31+
{
32+
label: 'more than...',
33+
value: DataConditionType.PERCENT_SESSIONS_COUNT,
34+
},
35+
{
36+
label: 'relatively higher than...',
37+
value: DataConditionType.PERCENT_SESSIONS_PERCENT,
38+
},
39+
]}
40+
onChange={(value: DataConditionType) => {
41+
onUpdateType(value);
42+
}}
43+
/>
44+
);
45+
}

static/app/views/automations/components/dataConditionNodes.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import {
88
import AgeComparisonNode from 'sentry/views/automations/components/actionFilters/ageComparison';
99
import EventAttributeNode from 'sentry/views/automations/components/actionFilters/eventAttribute';
1010
import EventFrequencyNode from 'sentry/views/automations/components/actionFilters/eventFrequency';
11+
import EventUniqueUserFrequencyNode from 'sentry/views/automations/components/actionFilters/eventUniqueUserFrequency';
1112
import IssueOccurrencesNode from 'sentry/views/automations/components/actionFilters/issueOccurrences';
1213
import IssuePriorityNode from 'sentry/views/automations/components/actionFilters/issuePriority';
1314
import LatestAdoptedReleaseNode from 'sentry/views/automations/components/actionFilters/latestAdoptedRelease';
1415
import LevelNode from 'sentry/views/automations/components/actionFilters/level';
16+
import PercentSessionsNode from 'sentry/views/automations/components/actionFilters/percentSessions';
1517
import TaggedEventNode from 'sentry/views/automations/components/actionFilters/taggedEvent';
1618

1719
interface DataConditionNodeProps {
@@ -136,4 +138,46 @@ export const dataConditionNodesMap = new Map<DataConditionType, DataConditionNod
136138
dataCondition: <EventFrequencyNode />,
137139
},
138140
],
141+
[
142+
DataConditionType.EVENT_UNIQUE_USER_FREQUENCY,
143+
{
144+
label: t('Number of users affected'),
145+
dataCondition: <EventUniqueUserFrequencyNode />,
146+
},
147+
],
148+
[
149+
DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_COUNT,
150+
{
151+
label: t('Number of users affected'),
152+
dataCondition: <EventUniqueUserFrequencyNode />,
153+
},
154+
],
155+
[
156+
DataConditionType.EVENT_UNIQUE_USER_FREQUENCY_PERCENT,
157+
{
158+
label: t('Number of users affected'),
159+
dataCondition: <EventUniqueUserFrequencyNode />,
160+
},
161+
],
162+
[
163+
DataConditionType.PERCENT_SESSIONS,
164+
{
165+
label: t('Percentage of sessions affected'),
166+
dataCondition: <PercentSessionsNode />,
167+
},
168+
],
169+
[
170+
DataConditionType.PERCENT_SESSIONS_COUNT,
171+
{
172+
label: t('Percentage of sessions affected'),
173+
dataCondition: <PercentSessionsNode />,
174+
},
175+
],
176+
[
177+
DataConditionType.PERCENT_SESSIONS_PERCENT,
178+
{
179+
label: t('Percentage of sessions affected'),
180+
dataCondition: <PercentSessionsNode />,
181+
},
182+
],
139183
]);

0 commit comments

Comments
 (0)