Skip to content

Commit a738281

Browse files
committed
Improve the template creation success indicator
1 parent 4a81e82 commit a738281

File tree

1 file changed

+71
-30
lines changed
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam

1 file changed

+71
-30
lines changed

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { conform, useForm } from "@conform-to/react";
22
import { parse } from "@conform-to/zod";
3-
import { BeakerIcon, StarIcon, RectangleStackIcon, TrashIcon } from "@heroicons/react/20/solid";
3+
import {
4+
BeakerIcon,
5+
StarIcon,
6+
RectangleStackIcon,
7+
TrashIcon,
8+
CheckCircleIcon,
9+
} from "@heroicons/react/20/solid";
10+
import { AnimatePresence, motion } from "framer-motion";
411
import { type ActionFunction, type LoaderFunctionArgs, json } from "@remix-run/server-runtime";
512
import { useCallback, useEffect, useRef, useState, useMemo } from "react";
613
import { typedjson, useTypedLoaderData } from "remix-typedjson";
@@ -355,6 +362,8 @@ function StandardTaskForm({
355362
paused: q.paused,
356363
}));
357364

365+
const [showTemplateCreatedSuccessMessage, setShowTemplateCreatedSuccessMessage] = useState(false);
366+
358367
const fetcher = useFetcher();
359368
const [
360369
form,
@@ -426,6 +435,7 @@ function StandardTaskForm({
426435
setTagsValue(template.tags ?? []);
427436
setQueueValue(template.queue);
428437
}}
438+
showTemplateCreatedSuccessMessage={showTemplateCreatedSuccessMessage}
429439
/>
430440
<RecentRunsPopover
431441
runs={runs}
@@ -741,6 +751,7 @@ function StandardTaskForm({
741751
}}
742752
getCurrentPayload={() => currentPayloadJson.current}
743753
getCurrentMetadata={() => currentMetadataJson.current}
754+
setShowCreatedSuccessMessage={setShowTemplateCreatedSuccessMessage}
744755
/>
745756
<Button
746757
type="submit"
@@ -804,6 +815,8 @@ function ScheduledTaskForm({
804815
);
805816
const [tagsValue, setTagsValue] = useState<string[]>(lastRun?.runTags ?? []);
806817

818+
const [showTemplateCreatedSuccessMessage, setShowTemplateCreatedSuccessMessage] = useState(false);
819+
807820
const queueItems = queues.map((q) => ({
808821
value: q.type === "task" ? `task/${q.name}` : q.name,
809822
label: q.name,
@@ -888,6 +901,7 @@ function ScheduledTaskForm({
888901
setExternalIdValue(template.scheduledTaskPayload?.externalId);
889902
setTimezoneValue(template.scheduledTaskPayload?.timezone ?? "UTC");
890903
}}
904+
showTemplateCreatedSuccessMessage={showTemplateCreatedSuccessMessage}
891905
/>
892906
<RecentRunsPopover
893907
runs={runs}
@@ -1243,6 +1257,7 @@ function ScheduledTaskForm({
12431257
}}
12441258
getCurrentPayload={() => ""}
12451259
getCurrentMetadata={() => ""}
1260+
setShowCreatedSuccessMessage={setShowTemplateCreatedSuccessMessage}
12461261
/>
12471262
<Button
12481263
type="submit"
@@ -1315,9 +1330,11 @@ function RecentRunsPopover<T extends StandardRun | ScheduledRun>({
13151330
function RunTemplatesPopover({
13161331
templates,
13171332
onTemplateSelected,
1333+
showTemplateCreatedSuccessMessage,
13181334
}: {
13191335
templates: RunTemplate[];
13201336
onTemplateSelected: (run: RunTemplate) => void;
1337+
showTemplateCreatedSuccessMessage: boolean;
13211338
}) {
13221339
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
13231340
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
@@ -1346,28 +1363,17 @@ function RunTemplatesPopover({
13461363
});
13471364

13481365
return (
1349-
<>
1366+
<div className="relative">
13501367
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
13511368
<PopoverTrigger asChild>
1352-
{templates.length === 0 ? (
1353-
<SimpleTooltip
1354-
button={
1355-
<Button
1356-
type="button"
1357-
variant="tertiary/small"
1358-
LeadingIcon={StarIcon}
1359-
disabled={true}
1360-
>
1361-
Templates
1362-
</Button>
1363-
}
1364-
content="No templates yet"
1365-
/>
1366-
) : (
1367-
<Button type="button" variant="tertiary/small" LeadingIcon={StarIcon}>
1368-
Templates
1369-
</Button>
1370-
)}
1369+
<Button
1370+
type="button"
1371+
variant="tertiary/small"
1372+
LeadingIcon={StarIcon}
1373+
disabled={templates.length === 0}
1374+
>
1375+
Templates
1376+
</Button>
13711377
</PopoverTrigger>
13721378
<PopoverContent className="min-w-[279px] p-0" align="end" sideOffset={6}>
13731379
<div className="max-h-80 overflow-y-auto">
@@ -1417,6 +1423,43 @@ function RunTemplatesPopover({
14171423
</PopoverContent>
14181424
</Popover>
14191425

1426+
<AnimatePresence mode="wait">
1427+
{showTemplateCreatedSuccessMessage && (
1428+
<motion.div
1429+
key="template-success-message"
1430+
initial={{
1431+
opacity: 0,
1432+
scale: 0.8,
1433+
y: -10,
1434+
}}
1435+
animate={{
1436+
opacity: 1,
1437+
scale: 1,
1438+
y: 0,
1439+
}}
1440+
exit={{
1441+
opacity: 0,
1442+
scale: 0.7,
1443+
y: -10,
1444+
transition: {
1445+
duration: 0.15,
1446+
ease: "easeOut",
1447+
},
1448+
}}
1449+
transition={{
1450+
type: "spring",
1451+
stiffness: 400,
1452+
damping: 25,
1453+
duration: 0.15,
1454+
}}
1455+
className="absolute -left-1/2 top-full z-10 mt-1 flex min-w-max max-w-64 items-center gap-1 rounded border border-charcoal-700 bg-background-bright px-2 py-1 text-xs shadow-md outline-none before:absolute before:-top-2 before:left-1/2 before:-translate-x-1/2 before:border-4 before:border-transparent before:border-b-charcoal-700 before:content-[''] after:absolute after:-top-[7px] after:left-1/2 after:-translate-x-1/2 after:border-4 after:border-transparent after:border-b-background-bright after:content-['']"
1456+
>
1457+
<CheckCircleIcon className="h-4 w-4 shrink-0 text-success" /> Template created
1458+
successfully
1459+
</motion.div>
1460+
)}
1461+
</AnimatePresence>
1462+
14201463
<Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
14211464
<DialogContent className="sm:max-w-sm">
14221465
<DialogHeader>Delete template</DialogHeader>
@@ -1444,14 +1487,15 @@ function RunTemplatesPopover({
14441487
</div>
14451488
</DialogContent>
14461489
</Dialog>
1447-
</>
1490+
</div>
14481491
);
14491492
}
14501493

14511494
function CreateTemplateModal({
14521495
rawTestTaskFormData,
14531496
getCurrentPayload,
14541497
getCurrentMetadata,
1498+
setShowCreatedSuccessMessage,
14551499
}: {
14561500
rawTestTaskFormData: {
14571501
environmentId: string;
@@ -1472,6 +1516,7 @@ function CreateTemplateModal({
14721516
};
14731517
getCurrentPayload: () => string;
14741518
getCurrentMetadata: () => string;
1519+
setShowCreatedSuccessMessage: (value: boolean) => void;
14751520
}) {
14761521
const submit = useSubmit();
14771522
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -1488,14 +1533,10 @@ function CreateTemplateModal({
14881533
lastSubmission.success === true
14891534
) {
14901535
setIsModalOpen(false);
1491-
toast.custom(
1492-
(t) => (
1493-
<ToastUI variant="success" message="Template created successfully" t={t as string} />
1494-
),
1495-
{
1496-
duration: 2000,
1497-
}
1498-
);
1536+
setShowCreatedSuccessMessage(true);
1537+
setTimeout(() => {
1538+
setShowCreatedSuccessMessage(false);
1539+
}, 2000);
14991540
}
15001541
}, [lastSubmission]);
15011542

0 commit comments

Comments
 (0)