Skip to content

Commit a41f799

Browse files
committed
Replace Remove channel button with No channel item, disable Save when clean
Pin a 'No channel' SelectItem at the top of the Slack channel dropdown so unsetting lives where the rest of channel selection lives. Mirror FeatureFlagsDialog's stableStringify(current) !== stableStringify(initial) dirty-check to keep Save disabled until the form actually changes.
1 parent 0509ca5 commit a41f799

1 file changed

Lines changed: 43 additions & 11 deletions

File tree

apps/webapp/app/components/errors/ConfigureErrorAlerts.tsx

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
} from "@heroicons/react/20/solid";
1010
import { useFetcher, useNavigate } from "@remix-run/react";
1111
import { SlackIcon } from "@trigger.dev/companyicons";
12-
import { Fragment, useEffect, useRef, useState } from "react";
12+
import { Fragment, useEffect, useMemo, useRef, useState } from "react";
13+
import stableStringify from "json-stable-stringify";
1314
import { z } from "zod";
1415
import { Button, LinkButton } from "~/components/primitives/Buttons";
1516
import { Callout, variantClasses } from "~/components/primitives/Callout";
@@ -104,6 +105,35 @@ export function ConfigureErrorAlerts({
104105
existingWebhooks.length > 0 ? [...existingWebhooks.map((w) => w.url), ""] : [""]
105106
);
106107

108+
const [formChangeTick, setFormChangeTick] = useState(0);
109+
const bumpFormChange = () => setFormChangeTick((n) => n + 1);
110+
111+
const isDirty = useMemo(() => {
112+
const initialSlackValue = existingSlackChannel
113+
? `${existingSlackChannel.channelId}/${existingSlackChannel.channelName}`
114+
: "";
115+
if ((selectedSlackChannelValue ?? "") !== initialSlackValue) return true;
116+
const currentEmails = emailFieldValues.current.filter((v) => v !== "");
117+
if (
118+
stableStringify(currentEmails) !==
119+
stableStringify(existingEmails.map((e) => e.email))
120+
)
121+
return true;
122+
const currentWebhooks = webhookFieldValues.current.filter((v) => v !== "");
123+
if (
124+
stableStringify(currentWebhooks) !==
125+
stableStringify(existingWebhooks.map((w) => w.url))
126+
)
127+
return true;
128+
return false;
129+
}, [
130+
selectedSlackChannelValue,
131+
existingSlackChannel,
132+
existingEmails,
133+
existingWebhooks,
134+
formChangeTick,
135+
]);
136+
107137
const [form, { emails, webhooks, slackChannel, slackIntegrationId }] = useForm({
108138
id: "configure-error-alerts",
109139
onValidate({ formData }) {
@@ -165,6 +195,7 @@ export function ConfigureErrorAlerts({
165195
icon={EnvelopeIcon}
166196
onChange={(e) => {
167197
emailFieldValues.current[index] = e.target.value;
198+
bumpFormChange();
168199
if (
169200
emailFields.length === emailFieldValues.current.length &&
170201
emailFieldValues.current.every((v) => v !== "")
@@ -218,6 +249,15 @@ export function ConfigureErrorAlerts({
218249
>
219250
{(matches) => (
220251
<>
252+
<SelectItem
253+
value=""
254+
className="border-b border-grid-bright text-text-dimmed"
255+
>
256+
<div className="flex items-center gap-1.5">
257+
<XMarkIcon className="size-4" />
258+
<span>No channel</span>
259+
</div>
260+
</SelectItem>
221261
{matches?.map((channel) => (
222262
<SelectItem
223263
key={channel.id}
@@ -243,15 +283,6 @@ export function ConfigureErrorAlerts({
243283
</Callout>
244284
)}
245285
<Hint>
246-
{selectedSlackChannelValue ? (
247-
<button
248-
type="button"
249-
onClick={() => setSelectedSlackChannelValue("")}
250-
className="mr-3 text-indigo-500 transition hover:text-indigo-400 focus-visible:focus-custom"
251-
>
252-
Remove channel
253-
</button>
254-
) : null}
255286
<TextLink to={organizationSlackIntegrationPath(organization)}>
256287
Manage Slack connection
257288
</TextLink>
@@ -327,6 +358,7 @@ export function ConfigureErrorAlerts({
327358
icon={GlobeAltIcon}
328359
onChange={(e) => {
329360
webhookFieldValues.current[index] = e.target.value;
361+
bumpFormChange();
330362
if (
331363
webhookFields.length === webhookFieldValues.current.length &&
332364
webhookFieldValues.current.every((v) => v !== "")
@@ -353,7 +385,7 @@ export function ConfigureErrorAlerts({
353385
<Button
354386
variant="primary/medium"
355387
type="submit"
356-
disabled={isSubmitting}
388+
disabled={!isDirty || isSubmitting}
357389
isLoading={isSubmitting}
358390
>
359391
{isSubmitting ? "Saving…" : "Save"}

0 commit comments

Comments
 (0)