diff --git a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.stories.tsx b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.stories.tsx index 26a5f9b9919..202fccf4839 100644 --- a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.stories.tsx @@ -55,40 +55,44 @@ export const WebhookNotConfigured: Story = { }, }; -export const Toggle: Story = { +export const ChangeMethod: Story = { play: async ({ canvasElement }) => { spyOn(API, "updateNotificationTemplateMethod").mockResolvedValue(); const user = userEvent.setup(); const canvas = within(canvasElement); const tmpl = MockSystemNotificationTemplates[4]; const option = await canvas.findByText(tmpl.name); - const li = option.closest("li"); - if (!li) { - throw new Error("Could not find li"); + const row = option.closest("[data-testid='notification-template-row']"); + if (!(row instanceof HTMLElement)) { + throw new Error("Could not find notification template row"); } - const toggleButton = within(li).getByRole("button", { - name: "Webhook", - }); - await user.click(toggleButton); + await user.click( + within(row).getByRole("combobox", { name: "Notification method" }), + ); + await user.click( + await within(document.body).findByRole("option", { name: "Webhook" }), + ); await within(document.body).findByText("Notification method updated."); }, }; -export const ToggleError: Story = { +export const ChangeMethodError: Story = { play: async ({ canvasElement }) => { spyOn(API, "updateNotificationTemplateMethod").mockRejectedValue({}); const user = userEvent.setup(); const canvas = within(canvasElement); const tmpl = MockSystemNotificationTemplates[4]; const option = await canvas.findByText(tmpl.name); - const li = option.closest("li"); - if (!li) { - throw new Error("Could not find li"); + const row = option.closest("[data-testid='notification-template-row']"); + if (!(row instanceof HTMLElement)) { + throw new Error("Could not find notification template row"); } - const toggleButton = within(li).getByRole("button", { - name: "Webhook", - }); - await user.click(toggleButton); + await user.click( + within(row).getByRole("combobox", { name: "Notification method" }), + ); + await user.click( + await within(document.body).findByRole("option", { name: "Webhook" }), + ); await within(document.body).findByText( "Failed to update notification method.", ); diff --git a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx index f524016157b..a0000ea5722 100644 --- a/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx +++ b/site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationEvents.tsx @@ -1,12 +1,4 @@ -import type { Interpolation, Theme } from "@emotion/react"; -import Card from "@mui/material/Card"; -import Divider from "@mui/material/Divider"; -import List from "@mui/material/List"; -import ListItem from "@mui/material/ListItem"; -import ListItemText, { listItemTextClasses } from "@mui/material/ListItemText"; -import ToggleButton from "@mui/material/ToggleButton"; -import ToggleButtonGroup from "@mui/material/ToggleButtonGroup"; -import { type FC, Fragment } from "react"; +import type { FC } from "react"; import { useMutation, useQueryClient } from "react-query"; import { toast } from "sonner"; import { getErrorDetail, getErrorMessage } from "#/api/errors"; @@ -18,10 +10,12 @@ import type { DeploymentValues } from "#/api/typesGenerated"; import { Alert } from "#/components/Alert/Alert"; import { Button } from "#/components/Button/Button"; import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "#/components/Tooltip/Tooltip"; + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "#/components/Select/Select"; import { castNotificationMethod, methodIcons, @@ -108,36 +102,35 @@ export const NotificationEvents: FC = ({ )} {Object.entries(templatesByGroup).map(([group, templates]) => ( - - - - - +
+
+ {group} +
- {templates.map((tpl, i) => { - const value = castNotificationMethod(tpl.method || defaultMethod); - const isLastItem = i === templates.length - 1; + {templates.map((tpl) => { + const value = castNotificationMethod(tpl.method || defaultMethod); - return ( - - - - - - {!isLastItem && } - - ); - })} - - + return ( +
+ {tpl.name} + +
+ ); + })} +
))} ); @@ -150,17 +143,19 @@ function requiredFieldsArePresent( return fields.every((field) => Boolean(obj[field])); } -type MethodToggleGroupProps = { +type MethodSelectProps = { templateId: string; + templateName: string; options: NotificationMethod[]; value: NotificationMethod; canEdit: boolean; }; -const MethodToggleGroup: FC = ({ +const MethodSelect: FC = ({ value, options, templateId, + templateName, canEdit, }) => { const queryClient = useQueryClient(); @@ -168,16 +163,14 @@ const MethodToggleGroup: FC = ({ updateNotificationTemplateMethod(templateId, queryClient), ); + const SelectedIcon = methodIcons[value]; + return ( - { - if (!method) { + onValueChange={async (method) => { + if (method === value) { return; } try { @@ -195,68 +188,31 @@ const MethodToggleGroup: FC = ({ } }} > - {options.map((method) => { - const Icon = methodIcons[method]; - const label = methodLabels[method]; - return ( - - - { - // Retain the value if the user clicks the same button, ensuring - // at least one value remains selected. - if (method === value) { - e.preventDefault(); - e.stopPropagation(); - return; - } - }} - > - - - - {label} - - ); - })} - + + + + + {methodLabels[value]} + + + + + {options.map((method) => { + const Icon = methodIcons[method]; + const label = methodLabels[method]; + return ( + + + + {label} + + + ); + })} + + ); }; - -const styles = { - listHeader: (theme) => ({ - background: theme.palette.background.paper, - borderBottom: `1px solid ${theme.palette.divider}`, - }), - listItemText: { - [`& .${listItemTextClasses.primary}`]: { - fontSize: 14, - fontWeight: 500, - }, - [`& .${listItemTextClasses.secondary}`]: { - fontSize: 14, - }, - }, - toggleGroup: (theme) => ({ - border: `1px solid ${theme.palette.divider}`, - borderRadius: 4, - }), - toggleButton: (theme) => ({ - border: 0, - borderRadius: 4, - fontSize: 16, - padding: "4px 8px", - color: theme.palette.text.disabled, - - "&:hover": { - color: theme.palette.text.primary, - }, - - "& svg": { - fontSize: "inherit", - }, - }), -} as Record>;