Skip to content

Commit

Permalink
Merge pull request #187 from FalkorDB/add-rename-and-copy
Browse files Browse the repository at this point in the history
fix #180 and 181 Add rename and copy
  • Loading branch information
AviAvni authored Apr 21, 2024
2 parents ed40fa2 + a8b37e2 commit 90574b8
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 44 deletions.
64 changes: 62 additions & 2 deletions app/api/graph/[graph]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,74 @@ export async function DELETE(request: NextRequest, { params }: { params: { graph

try {
if (graphId) {

const graph = client.selectGraph(graphId);

await graph.delete()

return NextResponse.json({ message: `${graphId} graph deleted` })
}
} catch (err: unknown) {
return NextResponse.json({ message: (err as Error).message }, { status: 400 })
}
}

// eslint-disable-next-line import/prefer-default-export
export async function POST(request: NextRequest, { params }: { params: { graph: string } }) {

const session = await getServerSession(authOptions)
const id = session?.user?.id
if (!id) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
}

const client = await getConnection(session.user)
if (!client) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
}

const graphId = params.graph;
const newName = request.nextUrl.searchParams.get("newName")

try {
if (!newName) throw (new Error("Missing parameter 'newName'"))

const graph = client.selectGraph(graphId);
await graph.copy(newName)

return NextResponse.json({ success: true })

} catch (err: unknown) {
return NextResponse.json({ message: (err as Error).message }, { status: 400 })
}
}

// eslint-disable-next-line import/prefer-default-export
export async function PATCH(request: NextRequest, { params }: { params: { graph: string } }) {

const session = await getServerSession(authOptions)
const id = session?.user?.id
if (!id) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
}

const client = await getConnection(session.user)
if (!client) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
}

const graphId = params.graph;
const newName = request.nextUrl.searchParams.get("newName")

try {
if (!newName) throw (new Error("Missing parameter 'newName'"))

const data = await client.connection.renameNX(graphId, newName);

if (!data) throw (new Error(`${newName} already exists`))

return NextResponse.json({ message: data })
} catch (err: unknown) {
return NextResponse.json({ message: (err as Error).message }, { status: 400 })
}
}
162 changes: 127 additions & 35 deletions app/graph/mainQuery.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { cn } from "@/lib/utils";
import { FormEvent, useEffect, useState } from "react";
import { Maximize, Menu, Play, Trash2 } from "lucide-react";
import { FormEvent, useEffect, useRef, useState } from "react";
import { Copy, Edit, Maximize, Menu, Play, Trash2 } from "lucide-react";
import Editor from "@monaco-editor/react";
import { useTheme } from "next-themes";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, AlertDialogHeader, AlertDialogFooter } from "@/components/ui/alert-dialog";
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { useToast } from "@/components/ui/use-toast";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import Combobox from "../components/combobox";

export default function MainQuery({ onSubmit, onDelete, className = "" }: {
Expand All @@ -16,11 +18,14 @@ export default function MainQuery({ onSubmit, onDelete, className = "" }: {
className: string,
}) {
const lineHeight = 40
const iconSize = 22
const [query, setQuery] = useState<string>("");
const [graphName, setGraphName] = useState("");
const { theme, systemTheme } = useTheme()
const darkmode = theme === "dark" || (theme === "system" && systemTheme === "dark")
const [graphs, setGraphs] = useState<string[]>([]);
const inputCopyRef = useRef<HTMLInputElement>(null)
const inputRenameRef = useRef<HTMLInputElement>(null)
const { toast } = useToast()

const getHeight = () => {
Expand Down Expand Up @@ -74,6 +79,45 @@ export default function MainQuery({ onSubmit, onDelete, className = "" }: {
})
}

const handelCopy = async () => {
const newName = inputCopyRef.current?.value
if (!newName) return
const response = await fetch(`/api/graph/${encodeURIComponent(graphName)}?newName=${newName}`, {
method: 'POST',
})
const json = await response.json()
if (response.status >= 300) {
toast({
title: "Error",
description: json.message,
})
return
}
setGraphs(prev => [...prev, newName])
}

const handelRename = async () => {
const newName = inputRenameRef.current?.value
if (!newName) return
const response = await fetch(`/api/graph/${encodeURIComponent(graphName)}?newName=${newName}`, {
method: 'PATCH',
})
const json = await response.json()
if (response.status >= 300) {
toast({
title: "Error",
description: json.message,
})
return
}
setGraphName(newName)
setGraphs(prev => [...prev.filter(name => name !== graphName), newName])
toast({
title: "Rename",
description: `Graph ${graphName} Rename to ${newName}`,
})
}

const addOption = (newGraph: string) => {
setGraphs((prevGraphs: string[]) => [...prevGraphs, newGraph]);
setGraphName(newGraph)
Expand Down Expand Up @@ -140,37 +184,85 @@ export default function MainQuery({ onSubmit, onDelete, className = "" }: {
</button>
{
graphName &&
<AlertDialog>
<DropdownMenu>
<DropdownMenuTrigger title="menu" className="pt-2 focus-visible:outline-none">
<Menu />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel className="text-center">
<h1>Actions</h1>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>
<AlertDialogTrigger className="w-full flex flex-row justify-around gap-4">
<span>Delete</span>
<Trash2 />
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure you?</AlertDialogTitle>
<AlertDialogDescription>
Are you absolutely sure you want to delete {graphName}?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => handelDelete(graphName)}>Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</AlertDialog>
<DropdownMenu>
<DropdownMenuTrigger title="menu" className="pt-2 focus-visible:outline-none">
<Menu />
</DropdownMenuTrigger>
<DropdownMenuContent>
<AlertDialog>
<AlertDialogTrigger asChild>
<DropdownMenuItem onSelect={(e) => e.preventDefault()} title="Delete">
<Trash2 size={iconSize} />
<DropdownMenuLabel>Delete</DropdownMenuLabel>
</DropdownMenuItem>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure you?</AlertDialogTitle>
<AlertDialogDescription>
Are you absolutely sure you want to delete {graphName}?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => handelDelete(graphName)}>Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<DropdownMenuSeparator />
<Dialog>
<DialogTrigger asChild>
<DropdownMenuItem onSelect={(e) => e.preventDefault()} title="Rename">
<Copy size={iconSize} />
<DropdownMenuLabel>Rename</DropdownMenuLabel>
</DropdownMenuItem>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>
<h1>Rename Graph</h1>
</DialogTitle>
<DialogDescription>
<Input required ref={inputRenameRef} placeholder="Enter Graph Name..." />
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild>
<Button onClick={() => handelRename()}>
<span>Rename</span>
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
<DropdownMenuSeparator />
<Dialog>
<DialogTrigger>
<DropdownMenuItem onSelect={(e) => e.preventDefault()} title="Copy">
<Edit size={iconSize} />
<DropdownMenuLabel>Copy</DropdownMenuLabel>
</DropdownMenuItem>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>
<h1>Copy Graph</h1>
</DialogTitle>
<DialogDescription>
<Input required ref={inputCopyRef} placeholder="Enter Copied Graph Name..." />
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild>
<Button onClick={() => handelCopy()}>
<span>Copy</span>
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
</DropdownMenuContent>
</DropdownMenu>
}
</form >
)
Expand Down
4 changes: 2 additions & 2 deletions app/graph/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useState } from "react";
import { signOut } from "next-auth/react";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Maximize2, X } from "lucide-react";
import Query from "./mainQuery";
import MainQuery from "./mainQuery";
import GraphSection from "./graphSection";
import { GraphState } from "./sectionQuery";

Expand Down Expand Up @@ -79,7 +79,7 @@ export default function Page() {
}
return (
<div className="h-full flex flex-col p-2 gap-y-2">
<Query
<MainQuery
onSubmit={runMainQuery}
onDelete={onDelete}
className="border rounded-lg border-gray-300 p-2"
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"falkordb": "beta",
"falkordb": "^6.0.1",
"lodash": "^4.17.21",
"lucide-react": "^0.301.0",
"monaco-editor": "^0.47.0",
Expand Down

0 comments on commit 90574b8

Please sign in to comment.