feat: able to remove share page deployment
This commit is contained in:
parent
b6be0bd462
commit
f8ac6fb251
35
web/src/components/ButtonActionLoader.tsx
Normal file
35
web/src/components/ButtonActionLoader.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
"use client";
|
||||
|
||||
import { LoadingIcon } from "@/components/LoadingIcon";
|
||||
import { callServerPromise } from "@/components/callServerPromise";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
export function ButtonAction({
|
||||
action,
|
||||
children,
|
||||
...rest
|
||||
}: {
|
||||
action: () => Promise<any>;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const [pending, setPending] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (pending) return;
|
||||
|
||||
setPending(true);
|
||||
await callServerPromise(action());
|
||||
setPending(false);
|
||||
|
||||
router.refresh();
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children} {pending && <LoadingIcon />}
|
||||
</button>
|
||||
);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import { ButtonAction } from "@/components/ButtonActionLoader";
|
||||
import { CodeBlock } from "@/components/CodeBlock";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@ -13,6 +14,7 @@ import { TableCell, TableRow } from "@/components/ui/table";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { getInputsFromWorkflow } from "@/lib/getInputsFromWorkflow";
|
||||
import { getRelativeTime } from "@/lib/getRelativeTime";
|
||||
import { removePublicShareDeployment } from "@/server/curdDeploments";
|
||||
import type { findAllDeployments } from "@/server/findAllRuns";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { headers } from "next/headers";
|
||||
@ -136,7 +138,14 @@ export function DeploymentDisplay({
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
) : (
|
||||
<div className="w-full text-right">
|
||||
<div className="w-full justify-end flex gap-2 py-1">
|
||||
<Button asChild className="gap-2" variant="outline" type="submit">
|
||||
<ButtonAction
|
||||
action={removePublicShareDeployment.bind(null, deployment.id)}
|
||||
>
|
||||
Remove
|
||||
</ButtonAction>
|
||||
</Button>
|
||||
<Button asChild className="gap-2">
|
||||
<Link href={`/share/${deployment.id}`} target="_blank">
|
||||
View Share Page <ExternalLink size={14} />
|
||||
|
@ -6,8 +6,16 @@ import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useMediaQuery } from "usehooks-ts";
|
||||
|
||||
export function NavbarMenu({ className }: { className?: string }) {
|
||||
const _isDesktop = useMediaQuery("(min-width: 1024px)");
|
||||
const [isDesktop, setIsDesktop] = useState(true);
|
||||
useEffect(() => {
|
||||
setIsDesktop(_isDesktop);
|
||||
}, [_isDesktop]);
|
||||
|
||||
const pathnames = usePathname();
|
||||
const pathname = `/${pathnames.split("/")[1]}`;
|
||||
|
||||
@ -31,42 +39,43 @@ export function NavbarMenu({ className }: { className?: string }) {
|
||||
return (
|
||||
<div className={cn("mr-2", className)}>
|
||||
{/* <div className="w-full h-full absolute inset-x-0 top-0 flex items-center justify-center pointer-events-none"> */}
|
||||
<Tabs
|
||||
defaultValue={pathname}
|
||||
className="w-[300px] hidden lg:flex pointer-events-auto"
|
||||
// onValueChange={(value) => {
|
||||
|
||||
// }}
|
||||
>
|
||||
<TabsList className="grid w-full grid-cols-3">
|
||||
{pages.map((page) => (
|
||||
<TabsTrigger
|
||||
key={page.name}
|
||||
value={page.path}
|
||||
onClick={() => {
|
||||
router.push(page.path);
|
||||
}}
|
||||
>
|
||||
{page.name}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
{isDesktop && (
|
||||
<Tabs
|
||||
defaultValue={pathname}
|
||||
className="w-[300px] flex pointer-events-auto"
|
||||
>
|
||||
<TabsList className="grid w-full grid-cols-3">
|
||||
{pages.map((page) => (
|
||||
<TabsTrigger
|
||||
key={page.name}
|
||||
value={page.path}
|
||||
onClick={() => {
|
||||
router.push(page.path);
|
||||
}}
|
||||
>
|
||||
{page.name}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
)}
|
||||
{/* </div> */}
|
||||
|
||||
<ScrollArea>
|
||||
<div className="w-full flex lg:hidden flex-col h-full">
|
||||
{pages.map((page) => (
|
||||
<Link
|
||||
key={page.name}
|
||||
href={page.path}
|
||||
className="p-2 hover:bg-gray-100/20 hover:underline"
|
||||
>
|
||||
{page.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
{!isDesktop && (
|
||||
<ScrollArea>
|
||||
<div className="w-full flex flex-col h-full">
|
||||
{pages.map((page) => (
|
||||
<Link
|
||||
key={page.name}
|
||||
href={page.path}
|
||||
className="p-2 hover:bg-gray-100/20 hover:underline"
|
||||
>
|
||||
{page.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
import { db } from "@/db/db";
|
||||
import type { DeploymentType } from "@/db/schema";
|
||||
import { deploymentsTable, workflowTable } from "@/db/schema";
|
||||
import { withServerPromise } from "@/server/withServerPromise";
|
||||
import { auth } from "@clerk/nextjs";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { revalidatePath } from "next/cache";
|
||||
@ -104,3 +105,17 @@ export async function findSharedDeployment(workflow_id: string) {
|
||||
|
||||
return deploymentData;
|
||||
}
|
||||
|
||||
export const removePublicShareDeployment = withServerPromise(
|
||||
async (deployment_id: string) => {
|
||||
// throw new Error("Not implemented");
|
||||
await db
|
||||
.delete(deploymentsTable)
|
||||
.where(
|
||||
and(
|
||||
eq(deploymentsTable.environment, "public-share"),
|
||||
eq(deploymentsTable.id, deployment_id)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user