-
Notifications
You must be signed in to change notification settings - Fork 371
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add empty Alerts Page + mock API behind feature flag
- Loading branch information
Showing
11 changed files
with
275 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { AlertsTable } from "@/src/features/alerts/AlertsTable"; | ||
import { api } from "@/src/utils/api"; | ||
import "@testing-library/jest-dom"; | ||
import { render, screen, cleanup } from "@testing-library/react"; | ||
|
||
afterEach(cleanup); | ||
|
||
jest.mock("../../../utils/api", () => ({ | ||
api: { | ||
alerts: { | ||
all: { | ||
useQuery: jest.fn(), | ||
}, | ||
}, | ||
}, | ||
})); | ||
|
||
describe("AlertsTable", () => { | ||
it("renders the table headers", () => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
(api.alerts.all.useQuery as jest.Mock).mockReturnValue({ | ||
isLoading: false, | ||
isError: false, | ||
data: [ | ||
{ | ||
id: "id-1", | ||
name: "Alert 1", | ||
triggerAttribute: "cost", | ||
triggerOperator: ">", | ||
triggerValue: 10, | ||
}, | ||
], | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} as any); | ||
|
||
render(<AlertsTable projectId="7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" />); | ||
|
||
const nameCol = screen.getByText(/Name/); | ||
expect(nameCol).toBeInTheDocument(); | ||
const triggerCol = screen.getByText(/Trigger/); | ||
expect(triggerCol).toBeInTheDocument(); | ||
|
||
const nameRow = screen.getByText(/Alert 1/); | ||
expect(nameRow).toBeInTheDocument(); | ||
const triggerRow = screen.getByText(/cost > 10/); | ||
expect(triggerRow).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** @jest-environment node */ | ||
import { pruneDatabase } from "@/src/__tests__/test-utils"; | ||
import { appRouter } from "@/src/server/api/root"; | ||
import { createInnerTRPCContext } from "@/src/server/api/trpc"; | ||
import { prisma } from "@/src/server/db"; | ||
import type { Session } from "next-auth"; | ||
|
||
describe("Alerts TRPC Router", () => { | ||
beforeEach(async () => await pruneDatabase()); | ||
afterEach(async () => await pruneDatabase()); | ||
|
||
const session: Session = { | ||
expires: "1", | ||
user: { | ||
id: "clgb17vnp000008jjere5g15i", | ||
name: "John Doe", | ||
projects: [ | ||
{ | ||
id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a", | ||
role: "ADMIN", | ||
name: "test", | ||
}, | ||
], | ||
featureFlags: { | ||
templateFlag: true, | ||
costAlerts: true, | ||
}, | ||
admin: true, | ||
}, | ||
}; | ||
|
||
const ctx = createInnerTRPCContext({ session }); | ||
const caller = appRouter.createCaller({ ...ctx, prisma }); | ||
|
||
test("alerts.all RPC returns an array of alerts", async () => { | ||
// await prisma.trace.create({ | ||
// data: { ...trace, projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" }, | ||
// }); | ||
|
||
const traces = await caller.alerts.all({ | ||
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a", | ||
}); | ||
expect(traces).toBeDefined(); | ||
expect(traces).toHaveLength(1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { DataTable } from "@/src/components/table/data-table"; | ||
import { type LangfuseColumnDef } from "@/src/components/table/types"; | ||
import { NewAlertButton } from "@/src/features/alerts/NewAlertButton"; | ||
import { api } from "@/src/utils/api"; | ||
import { type RouterOutput } from "@/src/utils/types"; | ||
|
||
type RowData = { | ||
key: { | ||
id: string; | ||
name: string; | ||
}; | ||
trigger: string; | ||
}; | ||
|
||
export function AlertsTable(props: { projectId: string }) { | ||
const alerts = api.alerts.all.useQuery({ | ||
projectId: props.projectId, | ||
}); | ||
|
||
const columns: LangfuseColumnDef<RowData>[] = [ | ||
{ | ||
accessorKey: "key", | ||
header: "Name", | ||
cell: ({ row }) => { | ||
const key: RowData["key"] = row.getValue("key"); | ||
return key.name; | ||
}, | ||
}, | ||
{ | ||
accessorKey: "trigger", | ||
header: "Trigger", | ||
}, | ||
]; | ||
|
||
const convertToTableRow = ( | ||
item: RouterOutput["alerts"]["all"][number], | ||
): RowData => { | ||
return { | ||
key: { id: item.id, name: item.name }, | ||
trigger: `${item.triggerAttribute} ${item.triggerOperator} ${item.triggerValue}`, | ||
}; | ||
}; | ||
|
||
return ( | ||
<div> | ||
<DataTable | ||
columns={columns} | ||
data={ | ||
alerts.isLoading | ||
? { isLoading: true, isError: false } | ||
: alerts.isError | ||
? { | ||
isLoading: false, | ||
isError: true, | ||
error: alerts.error.message, | ||
} | ||
: { | ||
isLoading: false, | ||
isError: false, | ||
data: alerts.data.map((t) => convertToTableRow(t)), | ||
} | ||
} | ||
/> | ||
<NewAlertButton projectId={props.projectId} className="mt-4" /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Button } from "@/src/components/ui/button"; | ||
import { | ||
Dialog, | ||
DialogContent, | ||
DialogHeader, | ||
DialogTitle, | ||
} from "@/src/components/ui/dialog"; | ||
import { DialogTrigger } from "@radix-ui/react-dialog"; | ||
import { LockIcon, PlusIcon } from "lucide-react"; | ||
import { useState } from "react"; | ||
|
||
export const NewAlertButton = (props: { | ||
projectId: string; | ||
className?: string; | ||
}) => { | ||
const [open, setOpen] = useState(false); | ||
// TODO: create scope and check access using useHasAccess | ||
const hasAccess = true; | ||
|
||
return ( | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
<Dialog open={hasAccess && open} onOpenChange={setOpen}> | ||
<DialogTrigger asChild> | ||
<Button | ||
variant="secondary" | ||
className={props.className} | ||
disabled={!hasAccess} | ||
> | ||
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */} | ||
{hasAccess ? ( | ||
<PlusIcon className="-ml-0.5 mr-1.5" aria-hidden="true" /> | ||
) : ( | ||
<LockIcon className="-ml-0.5 mr-1.5 h-3 w-3" aria-hidden="true" /> | ||
)} | ||
New Alert | ||
</Button> | ||
</DialogTrigger> | ||
<DialogContent className="sm:max-w-3xl"> | ||
<DialogHeader> | ||
<DialogTitle className="mb-5">Create new Alert</DialogTitle> | ||
</DialogHeader> | ||
{/* TODO: Form for creating new alert | ||
* <NewDatasetForm | ||
projectId={props.projectId} | ||
onFormSuccess={() => setOpen(false)} | ||
/> */} | ||
</DialogContent> | ||
</Dialog> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export const availableFlags = ["templateFlag"] as const; | ||
export const availableFlags = ["templateFlag", "costAlerts"] as const; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import Header from "@/src/components/layouts/header"; | ||
import { AlertsTable } from "@/src/features/alerts/AlertsTable"; | ||
import { useRouter } from "next/router"; | ||
|
||
export default function Alerts() { | ||
const router = useRouter(); | ||
const projectId = router.query.projectId as string; | ||
|
||
return ( | ||
<div> | ||
<Header title="Alerts" /> | ||
<AlertsTable projectId={projectId} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { z } from "zod"; | ||
|
||
import { | ||
createTRPCRouter, | ||
protectedProjectProcedure, | ||
} from "@/src/server/api/trpc"; | ||
import { paginationZod } from "@/src/utils/zod"; | ||
|
||
const AlertFilterOptions = z.object({ | ||
projectId: z.string(), // Required for protectedProjectProcedure | ||
...paginationZod, | ||
}); | ||
|
||
export const alertsRouter = createTRPCRouter({ | ||
all: protectedProjectProcedure.input(AlertFilterOptions).query(async () => { | ||
const alerts = [ | ||
{ | ||
id: "1", | ||
name: "Alert 1", | ||
triggerAttribute: "cost", | ||
triggerOperator: ">", | ||
triggerValue: 100, | ||
}, | ||
]; | ||
return Promise.resolve(alerts); | ||
}), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters