Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions kite-web/src/components/app/CommandList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AppEmptyPlaceholder from "./AppEmptyPlaceholder";
import { Skeleton } from "../ui/skeleton";
import AutoAnimate from "../common/AutoAnimate";
import CommandCreateDialog from "./CommandCreateDialog";
import FlowImportDialog from "./FlowImportDialog";
import { useCommands } from "@/lib/hooks/api";
import { CommandDeployDialog } from "./CommandDeployDialog";
import { useState } from "react";
Expand Down Expand Up @@ -39,9 +40,14 @@ export default function CommandList() {
one leaves no command to compare at all. Gating on "has
undeployed changes" made deleted commands unremovable. */}
<div className="flex gap-5 justify-between flex-col md:flex-row">
<CommandCreateDialog>
<Button>Create command</Button>
</CommandCreateDialog>
<div className="flex gap-5 flex-col md:flex-row">
<CommandCreateDialog>
<Button>Create command</Button>
</CommandCreateDialog>
<FlowImportDialog kind="command">
<Button variant="outline">Import command</Button>
</FlowImportDialog>
</div>

<CommandDeployDialog
open={deployDialogOpen}
Expand Down
11 changes: 11 additions & 0 deletions kite-web/src/components/app/CommandListEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
EllipsisIcon,
SlashSquareIcon,
Trash2Icon,
Share2Icon,
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
Expand All @@ -36,6 +37,7 @@ import {
import { Switch } from "../ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import CommandDuplicateDialog from "./CommandDuplicateDialog";
import FlowExportDialog from "./FlowExportDialog";

export default function CommandListEntry({ command }: { command: Command }) {
const router = useRouter();
Expand Down Expand Up @@ -156,6 +158,15 @@ export default function CommandListEntry({ command }: { command: Command }) {
Duplicate Command
</DropdownMenuItem>
</CommandDuplicateDialog>
<FlowExportDialog
title="Export Command"
shareData={{ flow_source: command.flow_source }}
>
<DropdownMenuItem onSelect={(e) => e.preventDefault()}>
<Share2Icon className="h-4 w-4 mr-2 text-muted-foreground" />
Export Command
</DropdownMenuItem>
</FlowExportDialog>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
18 changes: 12 additions & 6 deletions kite-web/src/components/app/EventListenerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import { useEventListeners } from "@/lib/hooks/api";
import EventListenerListEntry from "./EventListenerListEntry";
import AppEmptyPlaceholder from "./AppEmptyPlaceholder";
import EventListenerCreateDialog from "./EventListenerCreateDialog";
import FlowImportDialog from "./FlowImportDialog";

export default function EventListenerList() {
const listeners = useEventListeners();

const listenerCreateButton = (
<EventListenerCreateDialog>
<Button>Create event listener</Button>
</EventListenerCreateDialog>
const listenerActions = (
<div className="flex gap-5 flex-col md:flex-row">
<EventListenerCreateDialog>
<Button>Create event listener</Button>
</EventListenerCreateDialog>
<FlowImportDialog kind="event_listener">
<Button variant="outline">Import event listener</Button>
</FlowImportDialog>
</div>
);

return (
Expand All @@ -27,14 +33,14 @@ export default function EventListenerList() {
<AppEmptyPlaceholder
title="There are no event listeners"
description="You can start now by creating the first event listener!"
action={listenerCreateButton}
action={listenerActions}
/>
) : (
<>
{listeners.map((listener, i) => (
<EventListenerListEntry listener={listener!} key={i} />
))}
<div className="flex">{listenerCreateButton}</div>
{listenerActions}
</>
)}
</AutoAnimate>
Expand Down
14 changes: 14 additions & 0 deletions kite-web/src/components/app/EventListenerListEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
EllipsisIcon,
SatelliteDishIcon,
Trash2Icon,
Share2Icon,
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
Expand All @@ -35,6 +36,7 @@ import {
import { Switch } from "../ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import EventListenerDuplicateDialog from "./EventListenerDuplicateDialog";
import FlowExportDialog from "./FlowExportDialog";

export default function EventListenerListEntry({
listener,
Expand Down Expand Up @@ -139,6 +141,18 @@ export default function EventListenerListEntry({
Duplicate Event Listener
</DropdownMenuItem>
</EventListenerDuplicateDialog>
<FlowExportDialog
title="Export Event Listener"
shareData={{
source: listener.source,
flow_source: listener.flow_source,
}}
>
<DropdownMenuItem onSelect={(e) => e.preventDefault()}>
<Share2Icon className="h-4 w-4 mr-2 text-muted-foreground" />
Export Event Listener
</DropdownMenuItem>
</FlowExportDialog>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
60 changes: 60 additions & 0 deletions kite-web/src/components/app/FlowExportDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ReactNode, useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import { Button } from "../ui/button";
import { Textarea } from "../ui/textarea";
import { toast } from "sonner";

export default function FlowExportDialog({
title,
shareData,
children,
}: {
title: string;
shareData: Record<string, unknown>;
children: ReactNode;
}) {
const [open, setOpen] = useState(false);

const shareCode = open ? JSON.stringify(shareData) : "";

function copy() {
navigator.clipboard
.writeText(shareCode)
.then(() => {
toast.success("Copied to clipboard!");
setOpen(false);
})
.catch(() => toast.error("Failed to copy, use ctrl + c instead"));
}

return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>
Copy the share code below and import it into another app.
</DialogDescription>
</DialogHeader>
<Textarea
readOnly
value={shareCode}
className="min-h-[78px] max-h-[218px]"
onFocus={(e) => e.target.select()}
/>
<DialogFooter>
<Button onClick={copy}>Copy to clipboard</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
Loading