Skip to content

Commit 1960fd7

Browse files
authored
feat(aci): Add connected automations to detector details (#92786)
1 parent 41dc629 commit 1960fd7

File tree

3 files changed

+110
-20
lines changed

3 files changed

+110
-20
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
DataConditionHandlerGroupType,
66
} from 'sentry/types/workflowEngine/dataConditions';
77
import type {ApiQueryKey} from 'sentry/utils/queryClient';
8-
import {useApiQuery} from 'sentry/utils/queryClient';
8+
import {useApiQueries, useApiQuery} from 'sentry/utils/queryClient';
99
import useOrganization from 'sentry/utils/useOrganization';
1010

1111
const makeAutomationsQueryKey = (orgSlug: string): ApiQueryKey => [
@@ -58,3 +58,15 @@ export function useAvailableActionsQuery() {
5858
retry: false,
5959
});
6060
}
61+
62+
export function useDetectorQueriesByIds(automationIds: string[]) {
63+
const org = useOrganization();
64+
65+
return useApiQueries<Automation>(
66+
automationIds.map(id => makeAutomationQueryKey(org.slug, id)),
67+
{
68+
staleTime: 0,
69+
retry: false,
70+
}
71+
);
72+
}

static/app/views/detectors/components/connectedAutomationList.tsx

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,124 @@
1+
import {useEffect, useState} from 'react';
2+
3+
import {Flex} from 'sentry/components/container/flex';
14
import {Button} from 'sentry/components/core/button';
5+
import {ButtonBar} from 'sentry/components/core/button/buttonBar';
6+
import LoadingError from 'sentry/components/loadingError';
7+
import LoadingIndicator from 'sentry/components/loadingIndicator';
28
import {ActionCell} from 'sentry/components/workflowEngine/gridCell/actionCell';
39
import AutomationTitleCell from 'sentry/components/workflowEngine/gridCell/automationTitleCell';
410
import {TimeAgoCell} from 'sentry/components/workflowEngine/gridCell/timeAgoCell';
511
import {defineColumns, SimpleTable} from 'sentry/components/workflowEngine/simpleTable';
12+
import {IconChevron} from 'sentry/icons';
613
import {t} from 'sentry/locale';
714
import type {Automation} from 'sentry/types/workflowEngine/automations';
15+
import type {Detector} from 'sentry/types/workflowEngine/detectors';
16+
import {defined} from 'sentry/utils';
817
import useOrganization from 'sentry/utils/useOrganization';
18+
import {useDetectorQueriesByIds} from 'sentry/views/automations/hooks';
919
import {useAutomationActions} from 'sentry/views/automations/hooks/utils';
1020
import {makeAutomationDetailsPathname} from 'sentry/views/automations/pathnames';
1121

22+
const AUTOMATIONS_PER_PAGE = 10;
23+
1224
type Props = {
13-
automations: Automation[];
25+
automationIds: Detector['workflowIds'];
1426
connectedAutomationIds?: Set<string>;
1527
toggleConnected?: (id: string) => void;
1628
};
1729

1830
export function ConnectedAutomationsList({
19-
automations,
31+
automationIds,
2032
connectedAutomationIds,
2133
toggleConnected,
2234
}: Props) {
2335
const organization = useOrganization();
2436
const canEdit = connectedAutomationIds && !!toggleConnected;
37+
// TODO: There will eventually be a single api call to fetch a page of automations
38+
const queries = useDetectorQueriesByIds(automationIds);
39+
const [currentPage, setCurrentPage] = useState(0);
40+
const totalPages = Math.ceil(queries.length / AUTOMATIONS_PER_PAGE);
41+
42+
// Reset the page when the automationIds change
43+
useEffect(() => {
44+
setCurrentPage(0);
45+
}, [automationIds]);
46+
47+
const data = queries
48+
.map((query): ConnectedAutomationsData | undefined => {
49+
if (!query.data) {
50+
return undefined;
51+
}
52+
return {
53+
...query.data,
54+
link: makeAutomationDetailsPathname(organization.slug, query.data.id),
55+
connected: canEdit
56+
? {
57+
isConnected: connectedAutomationIds?.has(query.data.id),
58+
toggleConnected: () => toggleConnected?.(query.data.id),
59+
}
60+
: undefined,
61+
};
62+
})
63+
.filter(defined);
64+
65+
const isLoading = queries.some(query => query.isPending);
66+
const isError = queries.some(query => query.isError);
67+
68+
if (isError) {
69+
return <LoadingError />;
70+
}
2571

26-
const data = automations.map(automation => ({
27-
...automation,
28-
link: makeAutomationDetailsPathname(organization.slug, automation.id),
29-
connected: canEdit
30-
? {
31-
isConnected: connectedAutomationIds?.has(automation.id),
32-
toggleConnected: () => toggleConnected?.(automation.id),
33-
}
34-
: undefined,
35-
}));
72+
if (isLoading) {
73+
return <LoadingIndicator />;
74+
}
75+
76+
const handlePreviousPage = () => {
77+
setCurrentPage(prev => Math.max(0, prev - 1));
78+
};
79+
const handleNextPage = () => {
80+
setCurrentPage(prev => Math.min(totalPages - 1, prev + 1));
81+
};
82+
83+
const pagination = (
84+
<Flex justify="flex-end">
85+
<ButtonBar merged>
86+
<Button
87+
onClick={handlePreviousPage}
88+
disabled={currentPage === 0}
89+
aria-label={t('Previous page')}
90+
icon={<IconChevron direction="left" />}
91+
size="sm"
92+
/>
93+
<Button
94+
onClick={handleNextPage}
95+
disabled={currentPage === totalPages - 1}
96+
aria-label={t('Next page')}
97+
icon={<IconChevron direction="right" />}
98+
size="sm"
99+
/>
100+
</ButtonBar>
101+
</Flex>
102+
);
36103

37104
if (canEdit) {
38-
return <SimpleTable columns={connectedColumns} data={data} />;
105+
return (
106+
<Flex column>
107+
<SimpleTable columns={connectedColumns} data={data} />
108+
{pagination}
109+
</Flex>
110+
);
39111
}
40112

41113
return (
42-
<SimpleTable
43-
columns={baseColumns}
44-
data={data}
45-
fallback={t('No automations connected')}
46-
/>
114+
<Flex column>
115+
<SimpleTable
116+
columns={baseColumns}
117+
data={data}
118+
fallback={t('No automations connected')}
119+
/>
120+
{pagination}
121+
</Flex>
47122
);
48123
}
49124

static/app/views/detectors/detail.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import styled from '@emotion/styled';
55
import {Button} from 'sentry/components/core/button';
66
import {LinkButton} from 'sentry/components/core/button/linkButton';
77
import {DateTime} from 'sentry/components/dateTime';
8+
import ErrorBoundary from 'sentry/components/errorBoundary';
89
import ActorBadge from 'sentry/components/idBadge/actorBadge';
910
import {KeyValueTable, KeyValueTableRow} from 'sentry/components/keyValueTable';
1011
import LoadingError from 'sentry/components/loadingError';
@@ -110,7 +111,9 @@ export default function DetectorDetails() {
110111
<IssuesList />
111112
</Section>
112113
<Section title={t('Connected Automations')}>
113-
<ConnectedAutomationsList automations={[]} />
114+
<ErrorBoundary mini>
115+
<ConnectedAutomationsList automationIds={detector.workflowIds} />
116+
</ErrorBoundary>
114117
</Section>
115118
</DetailLayout.Main>
116119
<DetailLayout.Sidebar>

0 commit comments

Comments
 (0)