diff --git a/packages/api-v4/.changeset/pr-13193-changed-1765542569473.md b/packages/api-v4/.changeset/pr-13193-changed-1765542569473.md
new file mode 100644
index 00000000000..575de3bd42d
--- /dev/null
+++ b/packages/api-v4/.changeset/pr-13193-changed-1765542569473.md
@@ -0,0 +1,5 @@
+---
+"@linode/api-v4": Changed
+---
+
+Renamed updated_at, created_at to updated,created in NotificationChannelBase interface ([#13193](https://github.com/linode/manager/pull/13193))
diff --git a/packages/api-v4/src/cloudpulse/types.ts b/packages/api-v4/src/cloudpulse/types.ts
index 07dca57b539..12b8066f928 100644
--- a/packages/api-v4/src/cloudpulse/types.ts
+++ b/packages/api-v4/src/cloudpulse/types.ts
@@ -286,13 +286,13 @@ interface NotificationChannelAlerts {
interface NotificationChannelBase {
alerts: NotificationChannelAlerts[];
channel_type: ChannelType;
- created_at: string;
+ created: string;
created_by: string;
id: number;
label: string;
status: NotificationStatus;
type: AlertNotificationType;
- updated_at: string;
+ updated: string;
updated_by: string;
}
diff --git a/packages/manager/.changeset/pr-13193-upcoming-features-1765540702676.md b/packages/manager/.changeset/pr-13193-upcoming-features-1765540702676.md
new file mode 100644
index 00000000000..403ed960a55
--- /dev/null
+++ b/packages/manager/.changeset/pr-13193-upcoming-features-1765540702676.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Upcoming Features
+---
+
+Introduce Listing for ACLP-Alerting Notification channels with ordering, pagination ([#13193](https://github.com/linode/manager/pull/13193))
diff --git a/packages/manager/src/factories/cloudpulse/channels.ts b/packages/manager/src/factories/cloudpulse/channels.ts
index 9c96cd36e57..e36c53c1884 100644
--- a/packages/manager/src/factories/cloudpulse/channels.ts
+++ b/packages/manager/src/factories/cloudpulse/channels.ts
@@ -20,12 +20,12 @@ export const notificationChannelFactory =
subject: 'Sample Alert',
},
},
- created_at: new Date().toISOString(),
+ created: new Date().toISOString(),
created_by: 'user1',
id: Factory.each((i) => i),
label: Factory.each((id) => `Channel-${id}`),
status: 'Enabled',
type: 'custom',
- updated_at: new Date().toISOString(),
+ updated: new Date().toISOString(),
updated_by: 'user1',
});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.test.tsx
new file mode 100644
index 00000000000..57be8d91987
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.test.tsx
@@ -0,0 +1,161 @@
+import { screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+
+import { notificationChannelFactory } from 'src/factories/cloudpulse/channels';
+import { formatDate } from 'src/utilities/formatDate';
+import { renderWithTheme } from 'src/utilities/testHelpers';
+
+import { NotificationChannelListTable } from './NotificationChannelListTable';
+
+const mockScrollToElement = vi.fn();
+
+const ALERT_TYPE = 'alerts-definitions';
+
+describe('NotificationChannelListTable', () => {
+ it('should render the notification channel table headers', () => {
+ renderWithTheme(
+
+ );
+
+ expect(screen.getByText('Channel Name')).toBeVisible();
+ expect(screen.getByText('Alerts')).toBeVisible();
+ expect(screen.getByText('Channel Type')).toBeVisible();
+ expect(screen.getByText('Created By')).toBeVisible();
+ expect(screen.getByText('Last Modified')).toBeVisible();
+ expect(screen.getByText('Last Modified By')).toBeVisible();
+ });
+
+ it('should render the error message when error is provided', () => {
+ renderWithTheme(
+
+ );
+
+ expect(
+ screen.getByText('Error in fetching the notification channels')
+ ).toBeVisible();
+ });
+
+ it('should render notification channel rows', () => {
+ const updated = new Date().toISOString();
+ const channel = notificationChannelFactory.build({
+ channel_type: 'email',
+ created_by: 'user1',
+ label: 'Test Channel',
+ updated_by: 'user2',
+ updated,
+ });
+
+ renderWithTheme(
+
+ );
+
+ expect(screen.getByText('Test Channel')).toBeVisible();
+ expect(screen.getByText('Email')).toBeVisible();
+ expect(screen.getByText('user1')).toBeVisible();
+ expect(screen.getByText('user2')).toBeVisible();
+ expect(
+ screen.getByText(
+ formatDate(updated, {
+ format: 'MMM dd, yyyy, h:mm a',
+ })
+ )
+ ).toBeVisible();
+ });
+
+ it('should render the loading state', () => {
+ renderWithTheme(
+
+ );
+
+ screen.getByTestId('table-row-loading');
+ });
+
+ it('should render tooltip for Alerts column', async () => {
+ renderWithTheme(
+
+ );
+
+ const tooltipIcon = screen.getByTestId('tooltip-info-icon');
+ await userEvent.hover(tooltipIcon);
+
+ await waitFor(() => {
+ expect(
+ screen.getByText(
+ 'The number of alert definitions associated with the notification channel.'
+ )
+ ).toBeVisible();
+ });
+ });
+
+ it('should render multiple notification channels', () => {
+ const channels = notificationChannelFactory.buildList(5);
+
+ renderWithTheme(
+
+ );
+
+ channels.forEach((channel) => {
+ expect(screen.getByText(channel.label)).toBeVisible();
+ });
+ });
+
+ it('should display correct alerts count', () => {
+ const channel = notificationChannelFactory.build({
+ alerts: [
+ { id: 1, label: 'Alert 1', type: ALERT_TYPE, url: 'url1' },
+ { id: 2, label: 'Alert 2', type: ALERT_TYPE, url: 'url2' },
+ { id: 3, label: 'Alert 3', type: ALERT_TYPE, url: 'url3' },
+ ],
+ });
+
+ renderWithTheme(
+
+ );
+
+ expect(screen.getByText('3')).toBeVisible();
+ });
+
+ it('should render pagination footer', () => {
+ const channels = notificationChannelFactory.buildList(30);
+
+ renderWithTheme(
+
+ );
+
+ screen.getByRole('button', { name: /next/i });
+ });
+});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.tsx
new file mode 100644
index 00000000000..2566bda7132
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListTable.tsx
@@ -0,0 +1,194 @@
+import { TooltipIcon } from '@linode/ui';
+import { GridLegacy, TableBody, TableHead } from '@mui/material';
+import React from 'react';
+
+import Paginate from 'src/components/Paginate';
+import { PaginationFooter } from 'src/components/PaginationFooter/PaginationFooter';
+import { Table } from 'src/components/Table';
+import { TableCell } from 'src/components/TableCell';
+import { TableContentWrapper } from 'src/components/TableContentWrapper/TableContentWrapper';
+import { TableRow } from 'src/components/TableRow';
+import { TableSortCell } from 'src/components/TableSortCell';
+import { useOrderV2 } from 'src/hooks/useOrderV2';
+import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';
+
+import {
+ ChannelAlertsTooltipText,
+ ChannelListingTableLabelMap,
+} from './constants';
+import { NotificationChannelTableRow } from './NotificationChannelTableRow';
+
+import type { APIError, NotificationChannel } from '@linode/api-v4';
+import type { Order } from '@linode/utilities';
+
+export interface NotificationChannelListTableProps {
+ /**
+ * The error returned from the API call to fetch notification channels
+ */
+ error?: APIError[];
+ /**
+ * Indicates if the data is loading
+ */
+ isLoading: boolean;
+ /**
+ * The list of notification channels to display in the table
+ */
+ notificationChannels: NotificationChannel[];
+ /**
+ * Function to scroll to a specific element on the page
+ * @returns void
+ */
+ scrollToElement: () => void;
+}
+
+export const NotificationChannelListTable = React.memo(
+ (props: NotificationChannelListTableProps) => {
+ const { error, isLoading, notificationChannels, scrollToElement } = props;
+
+ const _error = error
+ ? getAPIErrorOrDefault(
+ error,
+ 'Error in fetching the notification channels.'
+ )
+ : undefined;
+
+ const handleScrollAndPageChange = (
+ page: number,
+ handlePageChange: (p: number) => void
+ ) => {
+ handlePageChange(page);
+ requestAnimationFrame(() => {
+ scrollToElement();
+ });
+ };
+
+ const handleScrollAndPageSizeChange = (
+ pageSize: number,
+ handlePageChange: (p: number) => void,
+ handlePageSizeChange: (p: number) => void
+ ) => {
+ handlePageSizeChange(pageSize);
+ handlePageChange(1);
+ requestAnimationFrame(() => {
+ scrollToElement();
+ });
+ };
+
+ const handleSortClick = (
+ orderBy: string,
+ handleOrderChange: (orderBy: string, order?: Order) => void,
+ handlePageChange: (page: number) => void,
+ order?: Order
+ ) => {
+ if (order) {
+ handleOrderChange(orderBy, order);
+ handlePageChange(1);
+ }
+ };
+
+ const { order, orderBy, handleOrderChange, sortedData } = useOrderV2({
+ data: notificationChannels,
+ initialRoute: {
+ defaultOrder: {
+ order: 'asc',
+ orderBy: 'label',
+ },
+ from: '/alerts/notification-channels',
+ },
+ preferenceKey: 'alerts-notification-channels',
+ });
+
+ return (
+
+ {({
+ count,
+ data: paginatedAndOrderedNotificationChannels,
+ handlePageChange,
+ handlePageSizeChange,
+ page,
+ pageSize,
+ }) => {
+ const handleTableSort = (orderBy: string, order?: Order) =>
+ handleSortClick(
+ orderBy,
+ handleOrderChange,
+ handlePageChange,
+ order
+ );
+
+ return (
+ <>
+
+
+
+
+ {ChannelListingTableLabelMap.map((value) => (
+
+ {value.colName}
+ {value.colName === 'Alerts' && (
+
+ )}
+
+ ))}
+
+
+
+
+
+
+
+ {paginatedAndOrderedNotificationChannels.map(
+ (channel: NotificationChannel) => (
+
+ )
+ )}
+
+
+
+
+ handleScrollAndPageChange(page, handlePageChange)
+ }
+ handleSizeChange={(pageSize) => {
+ handleScrollAndPageSizeChange(
+ pageSize,
+ handlePageChange,
+ handlePageSizeChange
+ );
+ }}
+ page={page}
+ pageSize={pageSize}
+ sx={{ border: 0 }}
+ />
+ >
+ );
+ }}
+
+ );
+ }
+);
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.test.tsx
new file mode 100644
index 00000000000..0e8d18f048c
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.test.tsx
@@ -0,0 +1,128 @@
+import { screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+
+import { notificationChannelFactory } from 'src/factories/cloudpulse/channels';
+import { renderWithTheme } from 'src/utilities/testHelpers';
+
+import { NotificationChannelListing } from './NotificationChannelListing';
+
+const queryMocks = vi.hoisted(() => ({
+ useAllAlertNotificationChannelsQuery: vi.fn().mockReturnValue({}),
+}));
+
+vi.mock('src/queries/cloudpulse/alerts', async () => {
+ const actual = await vi.importActual('src/queries/cloudpulse/alerts');
+ return {
+ ...actual,
+ useAllAlertNotificationChannelsQuery:
+ queryMocks.useAllAlertNotificationChannelsQuery,
+ };
+});
+
+const mockNotificationChannels = notificationChannelFactory.buildList(3);
+
+describe('NotificationChannelListing', () => {
+ beforeEach(() => {
+ queryMocks.useAllAlertNotificationChannelsQuery.mockReturnValue({
+ data: mockNotificationChannels,
+ error: null,
+ isLoading: false,
+ });
+ });
+
+ it('should render the notification channel listing with search field', () => {
+ renderWithTheme();
+
+ expect(
+ screen.getByPlaceholderText('Search for Notification Channels')
+ ).toBeVisible();
+ });
+
+ it('should render the notification channels table', () => {
+ renderWithTheme();
+
+ expect(screen.getByText('Channel Name')).toBeVisible();
+ expect(screen.getByText('Alerts')).toBeVisible();
+ expect(screen.getByText('Channel Type')).toBeVisible();
+ expect(screen.getByText('Created By')).toBeVisible();
+ expect(screen.getByText('Last Modified')).toBeVisible();
+ expect(screen.getByText('Last Modified By')).toBeVisible();
+ });
+
+ it('should render notification channel rows', () => {
+ renderWithTheme();
+
+ mockNotificationChannels.forEach((channel) => {
+ expect(screen.getByText(channel.label)).toBeVisible();
+ });
+ });
+
+ it('should filter notification channels based on search text', async () => {
+ const channels = [
+ notificationChannelFactory.build({ label: 'Email Channel' }),
+ notificationChannelFactory.build({ label: 'Slack Channel' }),
+ notificationChannelFactory.build({ label: 'PagerDuty Channel' }),
+ ];
+
+ queryMocks.useAllAlertNotificationChannelsQuery.mockReturnValue({
+ data: channels,
+ error: null,
+ isLoading: false,
+ });
+
+ renderWithTheme();
+
+ const searchField = screen.getByPlaceholderText(
+ 'Search for Notification Channels'
+ );
+
+ await userEvent.type(searchField, 'Email');
+
+ // Wait for debounce
+ await vi.waitFor(() => {
+ expect(screen.getByText('Email Channel')).toBeVisible();
+ expect(screen.queryByText('Slack Channel')).not.toBeInTheDocument();
+ expect(screen.queryByText('PagerDuty Channel')).not.toBeInTheDocument();
+ });
+ });
+
+ it('should show loading state', () => {
+ queryMocks.useAllAlertNotificationChannelsQuery.mockReturnValue({
+ data: null,
+ error: null,
+ isLoading: true,
+ });
+
+ renderWithTheme();
+
+ screen.getByTestId('table-row-loading');
+ });
+
+ it('should show error state', () => {
+ queryMocks.useAllAlertNotificationChannelsQuery.mockReturnValue({
+ data: null,
+ error: [{ reason: 'Error in fetching the notification channels' }],
+ isLoading: false,
+ });
+
+ renderWithTheme();
+
+ expect(
+ screen.getByText('Error in fetching the notification channels')
+ ).toBeVisible();
+ });
+
+ it('should render empty table when no notification channels exist', () => {
+ queryMocks.useAllAlertNotificationChannelsQuery.mockReturnValue({
+ data: [],
+ error: null,
+ isLoading: false,
+ });
+
+ renderWithTheme();
+
+ expect(screen.getByText('Channel Name')).toBeVisible();
+ expect(screen.getByText('No data to display.')).toBeVisible();
+ });
+});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.tsx
index 55559285b9f..4423cadcde4 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.tsx
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelListing.tsx
@@ -1,6 +1,59 @@
-import { Paper } from '@linode/ui';
+import { Box, Stack } from '@linode/ui';
import React from 'react';
+import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField';
+import { useAllAlertNotificationChannelsQuery } from 'src/queries/cloudpulse/alerts';
+
+import { scrollToElement } from '../../Utils/AlertResourceUtils';
+import { NotificationChannelListTable } from './NotificationChannelListTable';
+
export const NotificationChannelListing = () => {
- return Notification Channel Page; // Temporary placeholder
+ const {
+ data: notificationChannels,
+ error,
+ isLoading,
+ } = useAllAlertNotificationChannelsQuery();
+
+ const [searchText, setSearchText] = React.useState('');
+
+ const topRef = React.useRef(null);
+
+ const getNotificationChannelsList = React.useMemo(() => {
+ if (!notificationChannels) {
+ return [];
+ }
+ if (searchText) {
+ return notificationChannels.filter(({ label }) =>
+ label.toLowerCase().includes(searchText.toLowerCase())
+ );
+ }
+ return notificationChannels;
+ }, [notificationChannels, searchText]);
+
+ return (
+
+
+
+
+ scrollToElement(topRef.current)}
+ />
+
+ );
};
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.test.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.test.tsx
new file mode 100644
index 00000000000..dfce582e1cd
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.test.tsx
@@ -0,0 +1,146 @@
+import { screen } from '@testing-library/react';
+import React from 'react';
+
+import { notificationChannelFactory } from 'src/factories/cloudpulse/channels';
+import { formatDate } from 'src/utilities/formatDate';
+import { renderWithTheme, wrapWithTableBody } from 'src/utilities/testHelpers';
+
+import { NotificationChannelTableRow } from './NotificationChannelTableRow';
+
+describe('NotificationChannelTableRow', () => {
+ it('should render a notification channel row with all fields', () => {
+ const updated = new Date().toISOString();
+ const channel = notificationChannelFactory.build({
+ alerts: [
+ { id: 1, label: 'Alert 1', type: 'alerts-definitions', url: 'url1' },
+ { id: 2, label: 'Alert 2', type: 'alerts-definitions', url: 'url2' },
+ ],
+ channel_type: 'email',
+ created_by: 'user1',
+ label: 'Test Channel',
+ updated_by: 'user2',
+ updated,
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('Test Channel')).toBeVisible();
+ expect(screen.getByText('2')).toBeVisible(); // alerts count
+ expect(screen.getByText('Email')).toBeVisible();
+ expect(screen.getByText('user1')).toBeVisible();
+ expect(screen.getByText('user2')).toBeVisible();
+ expect(
+ screen.getByText(
+ formatDate(updated, {
+ format: 'MMM dd, yyyy, h:mm a',
+ })
+ )
+ ).toBeVisible();
+ });
+
+ it('should render channel type as Email for email type', () => {
+ const channel = notificationChannelFactory.build({
+ channel_type: 'email',
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('Email')).toBeVisible();
+ });
+
+ it('should render channel type as Slack for slack type', () => {
+ const channel = notificationChannelFactory.build({
+ channel_type: 'slack',
+ content: {
+ slack: {
+ message: 'message',
+ slack_channel: 'channel',
+ slack_webhook_url: 'url',
+ },
+ },
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('Slack')).toBeVisible();
+ });
+
+ it('should render channel type as PagerDuty for pagerduty type', () => {
+ const channel = notificationChannelFactory.build({
+ channel_type: 'pagerduty',
+ content: {
+ pagerduty: {
+ attributes: [],
+ description: 'desc',
+ service_api_key: 'key',
+ },
+ },
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('PagerDuty')).toBeVisible();
+ });
+
+ it('should render channel type as Webhook for webhook type', () => {
+ const channel = notificationChannelFactory.build({
+ channel_type: 'webhook',
+ content: {
+ webhook: {
+ http_headers: [],
+ webhook_url: 'url',
+ },
+ },
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('Webhook')).toBeVisible();
+ });
+
+ it('should render zero alerts count when no alerts are associated', () => {
+ const channel = notificationChannelFactory.build({
+ alerts: [],
+ });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText('0')).toBeVisible();
+ });
+
+ it('should render row with correct data-qa attribute', () => {
+ const channel = notificationChannelFactory.build({ id: 123 });
+
+ renderWithTheme(
+ wrapWithTableBody(
+
+ )
+ );
+
+ expect(screen.getByText(channel.label)).toBeVisible();
+ });
+});
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.tsx b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.tsx
new file mode 100644
index 00000000000..086e58d0f7a
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/NotificationChannelTableRow.tsx
@@ -0,0 +1,45 @@
+import { useProfile } from '@linode/queries';
+import React from 'react';
+
+import { TableCell } from 'src/components/TableCell';
+import { TableRow } from 'src/components/TableRow';
+import { formatDate } from 'src/utilities/formatDate';
+
+import { channelTypeMap } from '../../constants';
+
+import type { NotificationChannel } from '@linode/api-v4';
+
+interface NotificationChannelTableRowProps {
+ /**
+ * The notification channel details used by the component to fill the row details
+ */
+ notificationChannel: NotificationChannel;
+}
+
+export const NotificationChannelTableRow = (
+ props: NotificationChannelTableRowProps
+) => {
+ const { notificationChannel } = props;
+ const { data: profile } = useProfile();
+ const { id, label, channel_type, created_by, updated, updated_by, alerts } =
+ notificationChannel;
+ return (
+
+ {label}
+ {alerts.length}
+ {channelTypeMap[channel_type]}
+ {created_by}
+
+ {formatDate(updated, {
+ format: 'MMM dd, yyyy, h:mm a',
+ timezone: profile?.timezone,
+ })}
+
+ {updated_by}
+
+
+ );
+};
diff --git a/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/constants.ts
new file mode 100644
index 00000000000..070d4165f23
--- /dev/null
+++ b/packages/manager/src/features/CloudPulse/Alerts/NotificationChannels/NotificationsChannelsListing/constants.ts
@@ -0,0 +1,36 @@
+import type { NotificationChannel } from '@linode/api-v4';
+
+type ChannelListingTableLabel = {
+ colName: string;
+ label: keyof NotificationChannel;
+};
+
+export const ChannelListingTableLabelMap: ChannelListingTableLabel[] = [
+ {
+ colName: 'Channel Name',
+ label: 'label',
+ },
+ {
+ colName: 'Alerts',
+ label: 'alerts',
+ },
+ {
+ colName: 'Channel Type',
+ label: 'channel_type',
+ },
+ {
+ colName: 'Created By',
+ label: 'created_by',
+ },
+ {
+ colName: 'Last Modified',
+ label: 'updated',
+ },
+ {
+ colName: 'Last Modified By',
+ label: 'updated_by',
+ },
+];
+
+export const ChannelAlertsTooltipText =
+ 'The number of alert definitions associated with the notification channel.';
diff --git a/packages/manager/src/features/CloudPulse/Alerts/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/constants.ts
index 51becf87d3c..95670a13860 100644
--- a/packages/manager/src/features/CloudPulse/Alerts/constants.ts
+++ b/packages/manager/src/features/CloudPulse/Alerts/constants.ts
@@ -146,6 +146,13 @@ export const channelTypeOptions: Item[] = [
},
];
+export const channelTypeMap: Record = {
+ email: 'Email',
+ pagerduty: 'PagerDuty',
+ slack: 'Slack',
+ webhook: 'Webhook',
+};
+
export const metricOperatorTypeMap: Record = {
eq: '=',
gt: '>',
diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts
index 53b7dd66f8d..705f935cd84 100644
--- a/packages/manager/src/mocks/serverHandlers.ts
+++ b/packages/manager/src/mocks/serverHandlers.ts
@@ -3563,9 +3563,17 @@ export const handlers = [
return HttpResponse.json({});
}),
http.get('*/monitor/alert-channels', () => {
- return HttpResponse.json(
- makeResourcePage(notificationChannelFactory.buildList(7))
+ const notificationChannels = notificationChannelFactory.buildList(3);
+ notificationChannels.push(
+ notificationChannelFactory.build({
+ label: 'Email test channel',
+ updated: '2023-11-05T04:00:00',
+ updated_by: 'user3',
+ created_by: 'admin',
+ })
);
+ notificationChannels.push(...notificationChannelFactory.buildList(75));
+ return HttpResponse.json(makeResourcePage(notificationChannels));
}),
http.get('*/monitor/services', () => {
const response: ServiceTypesList = {