Skip to content

Commit 76486c3

Browse files
feat(aci): setup automation details (#92521)
basic setup, excluding the history + conditions panel also need to update the details endpoint to include `createdBy` <img width="1221" alt="Screenshot 2025-05-29 at 2 50 20 PM" src="https://github.com/user-attachments/assets/e2c2a4c4-c196-4f92-90a6-d9e4fb52c9da" /> --------- Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
1 parent 47b2309 commit 76486c3

File tree

5 files changed

+91
-152
lines changed

5 files changed

+91
-152
lines changed

static/app/types/workflowEngine/automations.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import type {DataConditionGroup} from 'sentry/types/workflowEngine/dataCondition
22

33
interface NewAutomation {
44
actionFilters: DataConditionGroup[];
5+
config: {frequency?: number};
56
detectorIds: string[];
7+
environment: string;
68
name: string;
79
triggers: DataConditionGroup;
810
disabled?: boolean;
911
}
1012

1113
export interface Automation extends Readonly<NewAutomation> {
14+
readonly dateCreated: string;
15+
readonly dateUpdated: string;
1216
readonly id: string;
1317
readonly lastTriggered: string;
1418
}

static/app/utils/useParams.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type ParamKeys =
1515
| 'appId'
1616
| 'appSlug'
1717
| 'authId'
18+
| 'automationId'
1819
| 'codeId'
1920
| 'dataExportId'
2021
| 'dashboardId'

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

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/* eslint-disable no-alert */
22
import {Fragment} from 'react';
3-
import styled from '@emotion/styled';
43

54
import {Flex} from 'sentry/components/container/flex';
65
import {Button} from 'sentry/components/core/button';
76
import {LinkButton} from 'sentry/components/core/button/linkButton';
87
import {DateTime} from 'sentry/components/dateTime';
98
import {KeyValueTable, KeyValueTableRow} from 'sentry/components/keyValueTable';
9+
import LoadingError from 'sentry/components/loadingError';
10+
import LoadingIndicator from 'sentry/components/loadingIndicator';
1011
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
1112
import TimeSince from 'sentry/components/timeSince';
1213
import {ActionsProvider} from 'sentry/components/workflowEngine/layout/actions';
@@ -15,79 +16,45 @@ import DetailLayout from 'sentry/components/workflowEngine/layout/detail';
1516
import Section from 'sentry/components/workflowEngine/ui/section';
1617
import {useWorkflowEngineFeatureGate} from 'sentry/components/workflowEngine/useWorkflowEngineFeatureGate';
1718
import {IconEdit} from 'sentry/icons';
18-
import {t} from 'sentry/locale';
19+
import {t, tct} from 'sentry/locale';
1920
import {space} from 'sentry/styles/space';
21+
import type {Detector} from 'sentry/types/workflowEngine/detectors';
22+
import getDuration from 'sentry/utils/duration/getDuration';
2023
import useOrganization from 'sentry/utils/useOrganization';
24+
import {useParams} from 'sentry/utils/useParams';
2125
import AutomationHistoryList from 'sentry/views/automations/components/automationHistoryList';
22-
import ConditionsPanel from 'sentry/views/automations/components/conditionsPanel';
2326
import ConnectedMonitorsList from 'sentry/views/automations/components/connectedMonitorsList';
27+
import {useAutomationQuery} from 'sentry/views/automations/hooks';
2428
import {makeAutomationBasePathname} from 'sentry/views/automations/pathnames';
25-
26-
function HistoryAndConnectedMonitors() {
27-
return (
28-
<div>
29-
<Section title={t('History')}>
30-
<AutomationHistoryList history={[]} />
31-
</Section>
32-
<Section title={t('Connected Monitors')}>
33-
<ConnectedMonitorsList monitors={[]} />
34-
</Section>
35-
</div>
36-
);
37-
}
38-
39-
function Details() {
40-
return (
41-
<Flex column gap={space(3)}>
42-
<Flex column gap={space(1)}>
43-
<SectionHeading>{t('Last Triggered')}</SectionHeading>
44-
<span>
45-
<TimeSince date={new Date()} />
46-
</span>
47-
</Flex>
48-
<Flex column gap={space(1)}>
49-
<SectionHeading>{t('Conditions')}</SectionHeading>
50-
<ConditionsPanel
51-
when_conditions={[
52-
t('An issue escalates'),
53-
t('A new event is captured for an issue'),
54-
]}
55-
if_conditions={[
56-
t('Issue is assigned to no one'),
57-
t('Current issue priority is high'),
58-
]}
59-
actions={[
60-
t(
61-
'Notify Suggested Assignees and if none can be found then notify Recently Active Members'
62-
),
63-
]}
64-
/>
65-
</Flex>
66-
<Flex column gap={space(1)}>
67-
<SectionHeading>{t('Details')}</SectionHeading>
68-
<KeyValueTable>
69-
<KeyValueTableRow
70-
keyName={t('Date created')}
71-
value={<DateTime date={new Date()} dateOnly year />}
72-
/>
73-
<KeyValueTableRow keyName={t('Created by')} value="Jane Doe" />
74-
<KeyValueTableRow
75-
keyName={t('Last modified')}
76-
value={<TimeSince date={new Date()} />}
77-
/>
78-
<KeyValueTableRow keyName={t('Team')} value="Platform" />
79-
</KeyValueTable>
80-
</Flex>
81-
</Flex>
82-
);
83-
}
29+
import {useDetectorQueriesByIds} from 'sentry/views/detectors/hooks';
8430

8531
export default function AutomationDetail() {
8632
const organization = useOrganization();
8733
useWorkflowEngineFeatureGate({redirect: true});
34+
const params = useParams<{automationId: string}>();
35+
36+
const {
37+
data: automation,
38+
isPending,
39+
isError,
40+
refetch,
41+
} = useAutomationQuery(params.automationId);
42+
43+
const detectorsQuery = useDetectorQueriesByIds(automation?.detectorIds || []);
44+
const detectors = detectorsQuery
45+
.map(result => result.data)
46+
.filter((detector): detector is Detector => detector !== undefined);
47+
48+
if (isPending) {
49+
return <LoadingIndicator />;
50+
}
51+
52+
if (isError) {
53+
return <LoadingError onRetry={refetch} />;
54+
}
8855

8956
return (
90-
<SentryDocumentTitle title={t('Automation')} noSuffix>
57+
<SentryDocumentTitle title={automation.name} noSuffix>
9158
<BreadcrumbsProvider
9259
crumb={{
9360
label: t('Automations'),
@@ -97,10 +64,47 @@ export default function AutomationDetail() {
9764
<ActionsProvider actions={<Actions />}>
9865
<DetailLayout>
9966
<DetailLayout.Main>
100-
<HistoryAndConnectedMonitors />
67+
<Section title={t('History')}>
68+
<AutomationHistoryList history={[]} />
69+
</Section>
70+
<Section title={t('Connected Monitors')}>
71+
<ConnectedMonitorsList monitors={detectors} />
72+
</Section>
10173
</DetailLayout.Main>
10274
<DetailLayout.Sidebar>
103-
<Details />
75+
<Section title={t('Last Triggered')}>
76+
{automation.lastTriggered ? (
77+
<Flex gap={space(1)}>
78+
<TimeSince date={automation.lastTriggered} />
79+
<Flex>
80+
(<DateTime date={automation.lastTriggered} year timeZone />)
81+
</Flex>
82+
</Flex>
83+
) : (
84+
t('Never')
85+
)}
86+
</Section>
87+
<Section title={t('Environment')}>
88+
{automation.environment || t('All environments')}
89+
</Section>
90+
<Section title={t('Action Interval')}>
91+
{tct('Every [frequency]', {
92+
frequency: getDuration((automation.config.frequency || 0) * 60),
93+
})}
94+
</Section>
95+
<Section title={t('Details')}>
96+
<KeyValueTable>
97+
<KeyValueTableRow
98+
keyName={t('Date created')}
99+
value={<DateTime date={automation.dateCreated} dateOnly year />}
100+
/>
101+
<KeyValueTableRow keyName={t('Created by')} value="placeholder" />
102+
<KeyValueTableRow
103+
keyName={t('Last modified')}
104+
value={<TimeSince date={automation.dateUpdated} />}
105+
/>
106+
</KeyValueTable>
107+
</Section>
104108
</DetailLayout.Sidebar>
105109
</DetailLayout>
106110
</ActionsProvider>
@@ -124,8 +128,3 @@ function Actions() {
124128
</Fragment>
125129
);
126130
}
127-
128-
const SectionHeading = styled('h4')`
129-
font-size: ${p => p.theme.fontSizeMedium};
130-
margin: 0;
131-
`;

static/app/views/automations/hooks/index.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ import type {ApiQueryKey} from 'sentry/utils/queryClient';
88
import {useApiQuery} from 'sentry/utils/queryClient';
99
import useOrganization from 'sentry/utils/useOrganization';
1010

11+
const makeAutomationsQueryKey = (orgSlug: string): ApiQueryKey => [
12+
`/organizations/${orgSlug}/workflows/`,
13+
];
14+
15+
const makeAutomationQueryKey = (orgSlug: string, automationId: string): ApiQueryKey => [
16+
`/organizations/${orgSlug}/workflows/${automationId}/`,
17+
];
18+
1119
interface UseAutomationsQueryOptions {
1220
query?: string;
1321
sort?: string;
@@ -21,6 +29,15 @@ export function useAutomationsQuery(_options: UseAutomationsQueryOptions = {}) {
2129
});
2230
}
2331

32+
export function useAutomationQuery(automationId: string) {
33+
const {slug} = useOrganization();
34+
35+
return useApiQuery<Automation>(makeAutomationQueryKey(slug, automationId), {
36+
staleTime: 0,
37+
retry: false,
38+
});
39+
}
40+
2441
export function useDataConditionsQuery(groupType: DataConditionHandlerGroupType) {
2542
const {slug} = useOrganization();
2643

@@ -33,10 +50,6 @@ export function useDataConditionsQuery(groupType: DataConditionHandlerGroupType)
3350
);
3451
}
3552

36-
const makeAutomationsQueryKey = (orgSlug: string): ApiQueryKey => [
37-
`/organizations/${orgSlug}/workflows/`,
38-
];
39-
4053
export function useAvailableActionsQuery() {
4154
const {slug} = useOrganization();
4255

0 commit comments

Comments
 (0)