Skip to content

Commit

Permalink
Merge pull request #645 from FalkorDB/small-changes
Browse files Browse the repository at this point in the history
Fix #644 small changes
  • Loading branch information
Anchel123 authored Feb 5, 2025
2 parents a5c2bb8 + 33e1ec3 commit 8c49231
Show file tree
Hide file tree
Showing 46 changed files with 625 additions and 861 deletions.
61 changes: 28 additions & 33 deletions app/api/graph/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ export type DataRow = {
export type Data = DataRow[]

export const DEFAULT_COLORS = [
"#7466FF",
"#FF66B3",
"#FF804D",
"#80E6E6"
"hsl(246, 100%, 70%)",
"hsl(330, 100%, 70%)",
"hsl(20, 100%, 65%)",
"hsl(180, 66%, 70%)"
]

export interface Query {
Expand Down Expand Up @@ -127,14 +127,12 @@ export class Graph {

private elements: GraphData;

private categoriesMap: Map<string, Category>;
private colorIndex: number = 0;

private categoriesColorIndex: number = 0;
private categoriesMap: Map<string, Category>;

private labelsMap: Map<string, Category>;

private labelsColorIndex: number = 0;

private nodesMap: Map<number, Node>;

private linksMap: Map<number, Link>;
Expand All @@ -154,7 +152,7 @@ export class Graph {
this.labelsMap = labelsMap;
this.nodesMap = nodesMap;
this.linksMap = edgesMap;
this.COLORS_ORDER_VALUE = colors || DEFAULT_COLORS
this.COLORS_ORDER_VALUE = [...(colors || DEFAULT_COLORS)]
}

get Id(): string {
Expand Down Expand Up @@ -274,23 +272,6 @@ export class Graph {
Object.entries(cell.properties).forEach(([key, value]) => {
currentNode.data[key] = isSchema ? getSchemaValue(value) : value;
});

// remove empty category if there are no more empty nodes category
if (Array.from(this.nodesMap.values()).every(n => n.category.some(c => c !== ""))) {
this.categories = this.categories.filter(l => l.name !== "").map(c => {
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
if (this.categoriesMap.get("")?.index! < c.index) {
c.index -= 1
this.categoriesMap.get(c.name)!.index = c.index
}
return c
})
this.categoriesMap.delete("")
this.categoriesColorIndex -= 1
this.elements.nodes.forEach(n => {
n.color = this.getCategoryColorValue(this.categoriesMap.get(n.category[0])?.index)
})
}
}

return currentNode
Expand Down Expand Up @@ -458,6 +439,13 @@ export class Graph {

link.curve = curve * 0.1
})

// remove empty category if there are no more empty nodes category
if (Array.from(this.nodesMap.values()).every(n => n.category.some(c => c !== ""))) {
this.categories = this.categories.filter(c => c.name !== "")
this.categoriesMap.delete("")
}

return newElements
}

Expand All @@ -484,8 +472,8 @@ export class Graph {
let c = this.categoriesMap.get(category)

if (!c) {
c = { name: category, index: this.categoriesColorIndex, show: true }
this.categoriesColorIndex += 1
c = { name: category, index: this.colorIndex, show: true }
this.colorIndex += 1
this.categoriesMap.set(c.name, c)
this.categories.push(c)
}
Expand All @@ -498,8 +486,8 @@ export class Graph {
let l = this.labelsMap.get(category)

if (!l) {
l = { name: category, index: this.labelsColorIndex, show: true }
this.labelsColorIndex += 1
l = { name: category, index: this.colorIndex, show: true }
this.colorIndex += 1
this.labelsMap.set(l.name, l)
this.labels.push(l)
}
Expand Down Expand Up @@ -543,7 +531,14 @@ export class Graph {
}
}

public getCategoryColorValue(index = 0): string {
return this.COLORS_ORDER_VALUE[index % this.COLORS_ORDER_VALUE.length]
public getCategoryColorValue(index = 0) {
if (index < this.COLORS_ORDER_VALUE.length) {
return this.COLORS_ORDER_VALUE[index];
}

const newColor = `hsl(${(index - 4) * 20}, 100%, 70%)`
this.COLORS_ORDER_VALUE.push(newColor)
DEFAULT_COLORS.push(newColor)
return newColor
}
}
}
2 changes: 1 addition & 1 deletion app/api/user/[user]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export async function PATCH(req: NextRequest, { params }: { params: Promise<{ us
}

const { user: username } = await params
const role = ROLE.get(req.nextUrl.searchParams.get("role") || "")
const role = ROLE.get(req.nextUrl.searchParams.get("userRole") || "")
try {
if (!role) throw new Error("Role is missing")

Expand Down
1 change: 0 additions & 1 deletion app/api/user/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ message: `User ${username} already exists` }, { status: 409 })
}
} catch (err: unknown) {
console.error(err)
// Just a workaround for https://github.com/redis/node-redis/issues/2745
}

Expand Down
32 changes: 20 additions & 12 deletions app/components/CreateGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
"use client"

import { useState } from "react"
import { AlertCircle, PlusCircle } from "lucide-react"
import { InfoIcon, PlusCircle } from "lucide-react"
import { prepareArg, securedFetch } from "@/lib/utils"
import { useToast } from "@/components/ui/use-toast"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { useSession } from "next-auth/react"
import DialogComponent from "./DialogComponent"
import Button from "./ui/Button"
import CloseDialog from "./CloseDialog"
Expand All @@ -23,7 +25,7 @@ export default function CreateGraph({
trigger = (
<Button
variant="Primary"
label="Create New Graph"
label={`Create New ${type}`}
>
<PlusCircle />
</Button>
Expand All @@ -33,7 +35,8 @@ export default function CreateGraph({
const [graphName, setGraphName] = useState("")
const [open, setOpen] = useState(false)
const { toast } = useToast()

const { data: session } = useSession()

const handleCreateGraph = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const name = graphName.trim()
Expand All @@ -48,13 +51,17 @@ export default function CreateGraph({
const q = 'RETURN 1'
const result = await securedFetch(`api/graph/${prepareArg(name)}/?query=${prepareArg(q)}`, {
method: "GET",
}, toast)
}, session?.user?.role, toast)

if (!result.ok) return

onSetGraphName(name)
setGraphName("")
setOpen(false)
toast({
title: "Graph created successfully",
description: "The graph has been created successfully",
})
}

return (
Expand All @@ -69,14 +76,15 @@ export default function CreateGraph({
handleCreateGraph(e)
}}>
<div className="flex gap-2 items-center">
<Button
className="text-nowrap"
type="button"
title={`${type} names can be edited later`}
>
<AlertCircle size={20} />
</Button>
<p className="font-normal text-2xl">Name your graph:</p>
<Tooltip>
<TooltipTrigger asChild>
<InfoIcon size={20} />
</TooltipTrigger>
<TooltipContent>
{`${type} names can be edited later`}
</TooltipContent>
</Tooltip>
<p className="font-normal text-2xl">Name your {type}:</p>
<Input
variant="primary"
ref={ref => ref?.focus()}
Expand Down
12 changes: 8 additions & 4 deletions app/components/DialogComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { cn } from "@/lib/utils";
import { ReactNode } from "react";
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
import CloseDialog from "./CloseDialog";

/* eslint-disable react/require-default-props */
Expand Down Expand Up @@ -36,10 +37,13 @@ export default function DialogComponent({
<CloseDialog />
</DialogHeader>
{
description &&
<DialogDescription className="p-4">
{description}
</DialogDescription>
description ?
<DialogDescription className="p-4">
{description}
</DialogDescription>
: <VisuallyHidden>
<DialogDescription />
</VisuallyHidden>
}
{children}
</DialogContent>
Expand Down
13 changes: 7 additions & 6 deletions app/components/EditorComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { Editor, Monaco } from "@monaco-editor/react"
import { useEffect, useRef, useState } from "react"
import * as monaco from "monaco-editor";
import { Maximize2 } from "lucide-react";
import { prepareArg, securedFetch } from "@/lib/utils";
import { useToast } from "@/components/ui/use-toast";
import { Session } from "next-auth";
import { useSession } from "next-auth/react";
import { prepareArg, securedFetch } from "@/lib/utils";
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
import { Graph } from "../api/graph/model";
import Button from "./ui/Button";
Expand All @@ -23,7 +23,6 @@ interface Props {
maximize: boolean
runQuery: (query: string) => void
graph: Graph
data: Session | null
}

const monacoOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
Expand Down Expand Up @@ -200,7 +199,7 @@ const LINE_HEIGHT = 38

const PLACEHOLDER = "Type your query here to start"

export default function EditorComponent({ currentQuery, historyQueries, setHistoryQueries, setCurrentQuery, maximize, runQuery, graph, data }: Props) {
export default function EditorComponent({ currentQuery, historyQueries, setHistoryQueries, setCurrentQuery, maximize, runQuery, graph }: Props) {

const [query, setQuery] = useState(currentQuery)
const placeholderRef = useRef<HTMLDivElement>(null)
Expand All @@ -217,6 +216,8 @@ export default function EditorComponent({ currentQuery, historyQueries, setHisto
currentQuery,
historyCounter: 0
})
const { data: session } = useSession()


useEffect(() => {
graphIdRef.current = graph.Id
Expand Down Expand Up @@ -279,9 +280,9 @@ export default function EditorComponent({ currentQuery, historyQueries, setHisto
}

const fetchSuggestions = async (q: string, detail: string): Promise<monaco.languages.CompletionItem[]> => {
const result = await securedFetch(`api/graph/${graphIdRef.current}/?query=${prepareArg(q)}&role=${data?.user.role}`, {
const result = await securedFetch(`api/graph/${graphIdRef.current}/?query=${prepareArg(q)}`, {
method: 'GET',
}, toast)
}, session?.user.role, toast)

if (!result) return []

Expand Down
18 changes: 8 additions & 10 deletions app/components/ExportGraph.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { useState } from "react"
import { ReactNode, useState } from "react"
import { prepareArg, securedFetch } from "@/lib/utils"
import { useToast } from "@/components/ui/use-toast"
import { useSession } from "next-auth/react"
import DialogComponent from "./DialogComponent"
import Button from "./ui/Button"
import CloseDialog from "./CloseDialog"

interface Props {
selectedValues: string[]
type: string
trigger: ReactNode
}

export default function ExportGraph({ selectedValues, type }: Props) {
export default function ExportGraph({ selectedValues, type, trigger }: Props) {

const [open, setOpen] = useState(false)
const { toast } = useToast()

const { data: session } = useSession()

const handleExport = () => {
selectedValues.map(async value => {
const name = `${value}${!type ? "_schema" : ""}`
const result = await securedFetch(`api/graph/${prepareArg(name)}/export`, {
method: "GET"
}, toast)
}, session?.user?.role, toast)

if (!result.ok) return

Expand Down Expand Up @@ -49,12 +52,7 @@ export default function ExportGraph({ selectedValues, type }: Props) {
<DialogComponent
open={open}
onOpenChange={setOpen}
trigger={
<Button
label="Export Data"
disabled={selectedValues.filter(value => value !== "").length === 0}
/>
}
trigger={trigger}
title="Export your graph"
description="Export a .dump file of your data"
>
Expand Down
Loading

0 comments on commit 8c49231

Please sign in to comment.