diff --git a/ui/app/GTM.tsx b/ui/app/GTM.tsx new file mode 100644 index 0000000..889963e --- /dev/null +++ b/ui/app/GTM.tsx @@ -0,0 +1,15 @@ +"use client" + +import { useEffect } from "react"; +import TagManager from "react-gtm-module"; + +export default function GTM() { + useEffect(() => { + const gtmId = process.env.NEXT_PUBLIC_GTM_ID + if (gtmId) { + TagManager.initialize({ gtmId }); + } + }, []); + + return null; +} \ No newline at end of file diff --git a/ui/app/components/VerticalBarChart.tsx b/ui/app/components/VerticalBarChart.tsx index 67f9756..491af2e 100644 --- a/ui/app/components/VerticalBarChart.tsx +++ b/ui/app/components/VerticalBarChart.tsx @@ -67,8 +67,8 @@ const VerticalBarChart: React.FC = ({ align: "top" as const, font: { weight: "bold" as const, - family: "Fira Code", - size: 18, + family: chartId !== "single" ? "Fira Code" : undefined, + size: chartId !== "single" ? 18 : undefined, }, color: "grey", // eslint-disable-next-line diff --git a/ui/app/components/dashboard.tsx b/ui/app/components/dashboard.tsx index 739d670..60e26a3 100644 --- a/ui/app/components/dashboard.tsx +++ b/ui/app/components/dashboard.tsx @@ -27,13 +27,13 @@ export default function DashBoard() { const [selectedOptions, setSelectedOptions] = React.useState< Record >({ - "Workload Type": ["concurrent"], + "Workload Type": ["single"], Vendors: ["falkordb", "neo4j"], Clients: ["40"], Throughput: ["2500"], Hardware: ["arm"], Queries: ["aggregate_expansion_4_with_filter"], - "Realistic Workload": ["1"], + // "Realistic Workload": ["1"], }); const fetchData = useCallback(async () => { @@ -206,7 +206,7 @@ export default function DashBoard() { hoverBackgroundColor: getBarColor(vendor), borderRadius: 8, barPercentage: 0.95, - categoryPercentage: 0.8, + categoryPercentage: 0.9, })); if (filteredUnrealistic.length >= 2) { @@ -274,29 +274,29 @@ export default function DashBoard() { const throughputRatio = minThroughput !== 0 ? Math.round(maxThroughput / minThroughput) : 0; - const memoryData = filteredResults.map((item) => { - const memoryValue = item.result["ram-usage"] ?? "0MB"; - const match = memoryValue.match(/([\d.]+)([a-zA-Z]+)/); - if (match) { - const value = parseFloat(match[1]); - const unit = match[2].toUpperCase(); - const memoryInMB = unit === "GB" ? value * 1024 : value; - return { - vendor: item.vendor, - memory: memoryInMB, - }; - } - - return { - vendor: item.vendor, - memory: 0, - }; - }); - - const maxMemoryUsage = Math.max(...memoryData.map((item) => item.memory)); - const minMemoryUsage = Math.min(...memoryData.map((item) => item.memory)); - const memoryUsageRatio = - minMemoryUsage !== 0 ? Math.round(maxMemoryUsage / minMemoryUsage) : 0; + // const memoryData = filteredResults.map((item) => { + // const memoryValue = item.result["ram-usage"] ?? "0MB"; + // const match = memoryValue.match(/([\d.]+)([a-zA-Z]+)/); + // if (match) { + // const value = parseFloat(match[1]); + // const unit = match[2].toUpperCase(); + // const memoryInMB = unit === "GB" ? value * 1024 : value; + // return { + // vendor: item.vendor, + // memory: memoryInMB, + // }; + // } + + // return { + // vendor: item.vendor, + // memory: 0, + // }; + // }); + + // const maxMemoryUsage = Math.max(...memoryData.map((item) => item.memory)); + // const minMemoryUsage = Math.min(...memoryData.map((item) => item.memory)); + // const memoryUsageRatio = + // minMemoryUsage !== 0 ? Math.round(maxMemoryUsage / minMemoryUsage) : 0; useEffect(() => { setGridKey((prevKey) => prevKey + 1); @@ -318,7 +318,7 @@ export default function DashBoard() { }; addOrReplaceChartData("throughputData", throughputData); - addOrReplaceChartData("memoryData", memoryData); + // addOrReplaceChartData("memoryData", memoryData); addOrReplaceChartData("latencyData", latencyDataForRealistic); } @@ -384,10 +384,10 @@ export default function DashBoard() { {selectedOptions["Workload Type"]?.includes("concurrent") && ( <>
-

THROUGHPUT

+

MAX THROUGHPUT

(HIGHER IS BETTER)

@@ -412,7 +412,7 @@ export default function DashBoard() {
-
@@ -439,7 +439,7 @@ export default function DashBoard() { />
- + */} )}
diff --git a/ui/app/data/sideBarData.ts b/ui/app/data/sideBarData.ts index bd29682..79244be 100644 --- a/ui/app/data/sideBarData.ts +++ b/ui/app/data/sideBarData.ts @@ -3,7 +3,7 @@ import { Cpu, Users, Activity, - BarChart, + // BarChart, Search, } from "lucide-react"; export const sidebarConfig: { @@ -76,13 +76,13 @@ export const sidebarConfig: { { id: "single_vertex_read", label: "Read Vertex" }, ], }, - { - title: "Realistic Workload", - description: "", - layout: "col", - icon: BarChart, - options: [{ id: "1", label: "100% Read / 0% Write" }], - }, + // { + // title: "Realistic Workload", + // description: "", + // layout: "col", + // icon: BarChart, + // options: [{ id: "1", label: "100% Read / 0% Write" }], + // }, ], }; diff --git a/ui/app/layout.tsx b/ui/app/layout.tsx index 412a0e0..ce9651f 100644 --- a/ui/app/layout.tsx +++ b/ui/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import "./globals.css"; import { Toaster } from "@/components/ui/toaster"; +import GTM from "./GTM"; export const metadata: Metadata = { title: "Benchmark by FalkorDB", @@ -15,6 +16,7 @@ export default function RootLayout({ return ( + {children} diff --git a/ui/package-lock.json b/ui/package-lock.json index 0220a40..1a957d9 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -32,6 +32,7 @@ "react": "^19.0.0", "react-chartjs-2": "^5.3.0", "react-dom": "^19.0.0", + "react-gtm-module": "^2.0.11", "react-icons": "^5.4.0", "react-resizable-panels": "^2.1.7", "tailwind-merge": "^2.6.0", @@ -43,6 +44,7 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "@types/react-gtm-module": "^2.0.4", "eslint": "^9", "eslint-config-next": "15.1.3", "postcss": "^8.4.49", @@ -1884,6 +1886,13 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/react-gtm-module": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/react-gtm-module/-/react-gtm-module-2.0.4.tgz", + "integrity": "sha512-5wPMWsUE5AI6O0B0K1/zbs0rFHBKu+7NWXQwDXhqvA12ooLD6W1AYiWZqR4UiOd7ixZDV1H5Ys301zEsqyIfNg==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.18.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz", @@ -6135,6 +6144,12 @@ "react": "^19.0.0" } }, + "node_modules/react-gtm-module": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", + "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==", + "license": "MIT" + }, "node_modules/react-icons": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", diff --git a/ui/package.json b/ui/package.json index 48f1f7f..42718df 100644 --- a/ui/package.json +++ b/ui/package.json @@ -33,6 +33,7 @@ "react": "^19.0.0", "react-chartjs-2": "^5.3.0", "react-dom": "^19.0.0", + "react-gtm-module": "^2.0.11", "react-icons": "^5.4.0", "react-resizable-panels": "^2.1.7", "tailwind-merge": "^2.6.0", @@ -44,6 +45,7 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "@types/react-gtm-module": "^2.0.4", "eslint": "^9", "eslint-config-next": "15.1.3", "postcss": "^8.4.49", diff --git a/ui/tests/logic/POM/mainPage.ts b/ui/tests/logic/POM/mainPage.ts index 8f7594e..57d9d00 100644 --- a/ui/tests/logic/POM/mainPage.ts +++ b/ui/tests/logic/POM/mainPage.ts @@ -72,6 +72,10 @@ export default class NavBarComponent extends BasePage { return this.page.locator("div[data-sidebar='content']"); } + private get sideBarWorkloadType(): (type: string) => Locator { + return (type: string) => this.page.locator("button", { hasText: type }); + } + /* General Functionality */ async hoverOnSideBarHardware(item: string): Promise { @@ -131,6 +135,10 @@ export default class NavBarComponent extends BasePage { await this.sideBarContent.evaluate((el) => el.scrollTo(0, el.scrollHeight)); } + async selectWorkloadType(type: string): Promise { + await this.sideBarWorkloadType(type).click(); + } + async isScrolledToBottomInSidebar(): Promise { return await this.sideBarContent.evaluate((el) => { return el.scrollTop + el.clientHeight >= el.scrollHeight; diff --git a/ui/tests/tests/sideBar.spec.ts b/ui/tests/tests/sideBar.spec.ts index f809fa9..bb220c5 100644 --- a/ui/tests/tests/sideBar.spec.ts +++ b/ui/tests/tests/sideBar.spec.ts @@ -64,6 +64,7 @@ test.describe("SideBar tests", () => { sideBarItems.forEach(({ item, expectedRes }) => { test(`Verify ${item} selection updates the chart results`, async () => { const sidebar = await browser.createNewPage(MainPage, urls.baseUrl); + await sidebar.selectWorkloadType("Concurrent"); const graphDetails = await sidebar.getGraphDetails(); await sidebar.clickOnSidebarSelection(item); const updatedGraphDetails = await sidebar.getGraphDetails(); @@ -99,6 +100,7 @@ test.describe("SideBar tests", () => { hoverItems.forEach(({ item, expectedRes }) => { test(`Verify hover behavior for hardware item: ${item}`, async () => { const sidebar = await browser.createNewPage(MainPage, urls.baseUrl); + await sidebar.selectWorkloadType("Concurrent"); await sidebar.hoverOnSideBarHardware(item); expect(await sidebar.isHoverElementVisible()).toBe(expectedRes); });