From 9604c30388f177c8a0073196c4a64e1ef5b74ddf Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:46:12 +0100
Subject: [PATCH 01/45] [OPIK-347]: add a prompts list page with fake data;
---
apps/opik-frontend/src/api/api.ts | 2 +
.../api/prompts/usePromptCreateMutation.ts | 60 +++++
.../api/prompts/usePromptDeleteMutation.ts | 38 +++
.../src/api/prompts/usePromptsList.ts | 131 ++++++++++
.../src/components/layout/SideBar/SideBar.tsx | 23 ++
.../pages/PromptsPage/AddPromptDialog.tsx | 110 +++++++++
.../PromptsPage/PromptRowActionsCell.tsx | 67 ++++++
.../pages/PromptsPage/PromptsPage.tsx | 227 ++++++++++++++++++
.../pages/PromptsPage/TagNameCell.tsx | 25 ++
apps/opik-frontend/src/router.tsx | 19 ++
apps/opik-frontend/src/types/prompts.ts | 8 +
11 files changed, 710 insertions(+)
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptsList.ts
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
create mode 100644 apps/opik-frontend/src/types/prompts.ts
diff --git a/apps/opik-frontend/src/api/api.ts b/apps/opik-frontend/src/api/api.ts
index 10ad7e277..34e94eb11 100644
--- a/apps/opik-frontend/src/api/api.ts
+++ b/apps/opik-frontend/src/api/api.ts
@@ -15,6 +15,8 @@ export const FEEDBACK_DEFINITIONS_REST_ENDPOINT =
"/v1/private/feedback-definitions/";
export const TRACES_REST_ENDPOINT = "/v1/private/traces/";
export const SPANS_REST_ENDPOINT = "/v1/private/spans/";
+export const PROMPTS_REST_ENDPOINT = "/v1/private/prompts/";
+
export type QueryConfig = Omit<
UseQueryOptions<
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
new file mode 100644
index 000000000..dc01359e9
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -0,0 +1,60 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { AxiosError } from "axios";
+import get from "lodash/get";
+
+import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import { useToast } from "@/components/ui/use-toast";
+import {Prompt} from "@/types/prompts";
+
+interface CreatePromptTemplate {
+ template: string;
+}
+
+type UsePromptCreateMutationParams = {
+ prompt: Partial & CreatePromptTemplate;
+ workspaceName: string;
+};
+
+const usePromptCreateMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({
+ prompt,
+ workspaceName,
+ }: UsePromptCreateMutationParams) => {
+ const { data, headers } = await api.post(PROMPTS_REST_ENDPOINT, {
+ ...prompt,
+ workspace_name: workspaceName,
+ });
+
+ return data;
+ },
+ onMutate: async (params: UsePromptCreateMutationParams) => {
+ return {
+ queryKey: ["prompts", { workspaceName: params.workspaceName }],
+ };
+ },
+ onError: (error: AxiosError) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: (data, error, variables, context) => {
+ if (context) {
+ return queryClient.invalidateQueries({ queryKey: context.queryKey });
+ }
+ },
+ });
+};
+
+export default usePromptCreateMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
new file mode 100644
index 000000000..509a31008
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
@@ -0,0 +1,38 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import get from "lodash/get";
+import { useToast } from "@/components/ui/use-toast";
+import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+
+type UsePromptDeleteMutationParams = {
+ promptId: string;
+};
+
+const usePromptDeleteMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({ promptId }: UsePromptDeleteMutationParams) => {
+ const { data } = await api.delete(PROMPTS_REST_ENDPOINT + promptId);
+ return data;
+ },
+ onError: (error) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: () => {
+ return queryClient.invalidateQueries({ queryKey: ["prompts"] });
+ },
+ });
+};
+
+export default usePromptDeleteMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
new file mode 100644
index 000000000..9007f2769
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -0,0 +1,131 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, {PROMPTS_REST_ENDPOINT, QueryConfig} from "@/api/api";
+import {Prompt} from "@/types/prompts";
+
+type UsePromptsListParams = {
+ workspaceName: string;
+ search?: string;
+ page: number;
+ size: number;
+};
+
+type UsePromptsListResponse = {
+ content: Prompt[];
+ total: number;
+};
+
+// ALEX
+const FAKE_PROMPTS: Prompt[] = [
+ {
+ "id": "4338ec03-6ee9-4635-b071-77849626b948",
+ "name": "Item 1123421342134341234812349123841239048132094812304123804301294",
+ "description": "This is a description for Item 1.",
+ "last_updated_at": "2022-04-15 00:00:00",
+ "created_at": "2020-09-09 00:00:00",
+ "versions_count": 6
+ },
+ {
+ "id": "2ac76571-520f-4664-9ad5-1439492ad557",
+ "name": "Item 2",
+ "description": "This is a description for Item 2.",
+ "last_updated_at": "2022-08-19 00:00:00",
+ "created_at": "2021-10-27 00:00:00",
+ "versions_count": 4
+ },
+ {
+ "id": "3ba74f16-698f-4318-9427-d26403bc117b",
+ "name": "Item 3",
+ "description": "This is a description for Item 3.",
+ "last_updated_at": "2023-12-12 00:00:00",
+ "created_at": "2021-10-08 00:00:00",
+ "versions_count": 5
+ },
+ {
+ "id": "bbef9b6c-d991-4132-9c08-24e1584ccea2",
+ "name": "Item 4",
+ "description": "This is a description for Item 4.",
+ "last_updated_at": "2023-05-14 00:00:00",
+ "created_at": "2023-01-04 00:00:00",
+ "versions_count": 10
+ },
+ {
+ "id": "57c82e2b-3d75-4f16-87ac-3201554ea84d",
+ "name": "Item 5",
+ "description": "This is a description for Item 5.",
+ "last_updated_at": "2022-06-10 00:00:00",
+ "created_at": "2021-10-06 00:00:00",
+ "versions_count": 4
+ },
+ {
+ "id": "caad2d07-6be4-4e30-8e54-45928c4c675c",
+ "name": "Item 6",
+ "description": "This is a description for Item 6.",
+ "last_updated_at": "2023-11-07 00:00:00",
+ "created_at": "2022-04-26 00:00:00",
+ "versions_count": 7
+ },
+ {
+ "id": "955439b8-2199-4edb-bfff-0becef27f477",
+ "name": "Item 7",
+ "description": "This is a description for Item 7.",
+ "last_updated_at": "2023-09-21 00:00:00",
+ "created_at": "2023-08-15 00:00:00",
+ "versions_count": 5
+ },
+ {
+ "id": "059452b9-9050-4b99-893f-8e809adae877",
+ "name": "Item 8",
+ "description": "This is a description for Item 8.",
+ "last_updated_at": "2023-04-10 00:00:00",
+ "created_at": "2022-09-22 00:00:00",
+ "versions_count": 8
+ },
+ {
+ "id": "c46f907a-7e35-4d35-a482-fb4a7fee3967",
+ "name": "Item 9",
+ "description": "This is a description for Item 9.",
+ "last_updated_at": "2023-12-22 00:00:00",
+ "created_at": "2023-05-13 00:00:00",
+ "versions_count": 8
+ },
+ {
+ "id": "c4365771-f654-4434-9272-8e22f623906b",
+ "name": "Item 10",
+ "description": "This is a description for Item 10.",
+ "last_updated_at": "2023-09-09 00:00:00",
+ "created_at": "2022-12-02 00:00:00",
+ "versions_count": 6
+ }
+]
+
+
+const getPromptsList = async (
+ { signal }: QueryFunctionContext,
+ { workspaceName, search, size, page }: UsePromptsListParams,
+) => {
+ // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
+ // signal,
+ // params: {
+ // workspace_name: workspaceName,
+ // ...(search && { name: search }),
+ // size,
+ // page,
+ // },
+ // });
+
+ return {
+ content: FAKE_PROMPTS,
+ total: FAKE_PROMPTS.length,
+ };
+};
+
+export default function usePromptsList(
+ params: UsePromptsListParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompts", params],
+ queryFn: (context) => getPromptsList(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index e3effc3cd..a45bcf1db 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -11,6 +11,7 @@ import {
MessageSquare,
PanelLeftClose,
MessageCircleQuestion,
+ FileTerminal
} from "lucide-react";
import { keepPreviousData } from "@tanstack/react-query";
@@ -27,6 +28,7 @@ import { buildDocsUrl, cn } from "@/lib/utils";
import Logo from "@/components/layout/Logo/Logo";
import usePluginsStore from "@/store/PluginsStore";
import ProvideFeedbackDialog from "@/components/layout/SideBar/FeedbackDialog/ProvideFeedbackDialog";
+import usePromptsList from "@/api/prompts/usePromptsList";
enum MENU_ITEM_TYPE {
link = "link",
@@ -53,6 +55,14 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
label: "Projects",
count: "projects",
},
+ {
+ id: "prompts",
+ path: "/$workspaceName/prompts",
+ type: MENU_ITEM_TYPE.router,
+ icon: FileTerminal,
+ label: "Prompts",
+ count: "prompts",
+ },
{
id: "datasets",
path: "/$workspaceName/datasets",
@@ -204,11 +214,24 @@ const SideBar: React.FunctionComponent = ({
},
);
+ const { data: promptsData } = usePromptsList(
+ {
+ workspaceName,
+ page: 1,
+ size: 1,
+ },
+ {
+ placeholderData: keepPreviousData,
+ enabled: expanded,
+ },
+ );
+
const countDataMap: Record = {
projects: projectData?.total,
datasets: datasetsData?.total,
experiments: experimentsData?.total,
feedbackDefinitions: feedbackDefinitions?.total,
+ prompts: promptsData?.total
};
const bottomMenuItems: MenuItem[] = [
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
new file mode 100644
index 000000000..437497c60
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
@@ -0,0 +1,110 @@
+import React, {useCallback, useState} from "react";
+import { Button } from "@/components/ui/button";
+import {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import useAppStore from "@/store/AppStore";
+import { Textarea } from "@/components/ui/textarea";
+import usePromptCreateMutation from "@/api/prompts/usePromptCreateMutation";
+import {Prompt} from "@/types/prompts";
+import {AccordionContent, AccordionItem, AccordionTrigger, Accordion} from "@/components/ui/accordion";
+
+type AddPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+ onPromptCreated?: (prompt: Prompt) => void;
+};
+
+const AddPromptDialog: React.FunctionComponent = ({
+ open,
+ setOpen,
+ onPromptCreated,
+}) => {
+ const workspaceName = useAppStore((state) => state.activeWorkspaceName);
+ const promptCreateMutation = usePromptCreateMutation();
+ const [name, setName] = useState("");
+ const [prompt, setPrompt] = useState("");
+ const [description, setDescription] = useState("");
+
+ const isValid = Boolean(name.length && prompt.length);
+
+ const createPrompt = useCallback(() => {
+ promptCreateMutation.mutate(
+ {
+ prompt: {
+ name,
+ template: prompt,
+ ...(description ? { description } : {}),
+ },
+ workspaceName,
+ },
+ { onSuccess: onPromptCreated },
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [name, description, workspaceName, onPromptCreated]);
+
+ return (
+
+ );
+};
+
+export default AddPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
new file mode 100644
index 000000000..3f77a0793
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
@@ -0,0 +1,67 @@
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Button } from "@/components/ui/button";
+import { MoreHorizontal, Trash } from "lucide-react";
+import React, { useCallback, useRef, useState } from "react";
+import { CellContext } from "@tanstack/react-table";
+import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
+import {Prompt} from "@/types/prompts";
+import usePromptDeleteMutation from "@/api/prompts/usePromptDeleteMutation";
+
+export const PromptRowActionsCell: React.FunctionComponent<
+ CellContext
+> = ({ row }) => {
+ const resetKeyRef = useRef(0);
+ const prompt = row.original;
+ const [open, setOpen] = useState(false);
+
+ const promptDeleteMutation = usePromptDeleteMutation();
+
+ const deletePromptHandler = useCallback(() => {
+ promptDeleteMutation.mutate({
+ promptId: prompt.id,
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [prompt.id]);
+
+ return (
+ e.stopPropagation()}
+ >
+
+
+
+
+
+
+ {
+ setOpen(true);
+ resetKeyRef.current = resetKeyRef.current + 1;
+ }}
+ >
+
+ Delete
+
+
+
+
+
+ );
+};
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
new file mode 100644
index 000000000..ad83388a2
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -0,0 +1,227 @@
+import React, { useCallback, useMemo, useRef, useState } from "react";
+import { useNavigate } from "@tanstack/react-router";
+import { keepPreviousData } from "@tanstack/react-query";
+import DataTable from "@/components/shared/DataTable/DataTable";
+import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
+import DataTableNoData from "@/components/shared/DataTableNoData/DataTableNoData";
+import IdCell from "@/components/shared/DataTableCells/IdCell";
+import Loader from "@/components/shared/Loader/Loader";
+import { Button } from "@/components/ui/button";
+import useAppStore from "@/store/AppStore";
+import SearchInput from "@/components/shared/SearchInput/SearchInput";
+import { formatDate } from "@/lib/date";
+import { COLUMN_TYPE, ColumnData } from "@/types/shared";
+import useLocalStorageState from "use-local-storage-state";
+import { convertColumnDataToColumn } from "@/lib/table";
+import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
+import usePromptsList from "@/api/prompts/usePromptsList";
+import {Prompt} from "@/types/prompts";
+import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
+import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
+import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
+import ResourceCell from "@/components/shared/DataTableCells/ResourceCell";
+import {RESOURCE_TYPE} from "@/components/shared/ResourceLink/ResourceLink";
+
+const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
+const COLUMNS_WIDTH_KEY = "prompts-columns-width";
+const COLUMNS_ORDER_KEY = "prompts-columns-order";
+
+// ALEX
+// ASK ABOUT PUTTING IT INTO A DIFFERENT HOOK FOR COLUMN STATES
+// ADD A key to the sidebar
+
+export const DEFAULT_COLUMNS: ColumnData[] = [
+ {
+ id: "id",
+ label: "ID",
+ type: COLUMN_TYPE.string,
+ cell: IdCell as never,
+ },
+ {
+ id: "name",
+ label: "Name",
+ type: COLUMN_TYPE.string,
+ cell: TagNameCell as never
+ },
+ {
+ id: "versions_count",
+ label: "Versions",
+ type: COLUMN_TYPE.number,
+ },
+ {
+ id: "last_updated_at",
+ label: "Last updated",
+ type: COLUMN_TYPE.time,
+ accessorFn: (row) => formatDate(row.last_updated_at),
+ },
+ {
+ id: "description",
+ label: "Description",
+ type: COLUMN_TYPE.string,
+ },
+];
+
+export const DEFAULT_SELECTED_COLUMNS: string[] = [
+ "name",
+ "versions_count",
+ "last_updated_at",
+ "description",
+];
+
+const PromptsPage: React.FunctionComponent = () => {
+ const navigate = useNavigate();
+ const workspaceName = useAppStore((state) => state.activeWorkspaceName);
+
+ const resetDialogKeyRef = useRef(0);
+ const [openDialog, setOpenDialog] = useState(false);
+ const [search, setSearch] = useState("");
+ const [page, setPage] = useState(1);
+ const [size, setSize] = useState(10);
+ const { data, isPending } = usePromptsList(
+ {
+ workspaceName,
+ search,
+ page,
+ size,
+ },
+ {
+ placeholderData: keepPreviousData,
+ },
+ );
+
+ const prompts = data?.content ?? [];
+ const total = data?.total ?? 0;
+ const noData = !search;
+ const noDataText = noData ? "There are no prompts yet" : "No search results";
+
+ const [selectedColumns, setSelectedColumns] = useLocalStorageState(
+ SELECTED_COLUMNS_KEY,
+ {
+ defaultValue: DEFAULT_SELECTED_COLUMNS,
+ },
+ );
+
+ const [columnsOrder, setColumnsOrder] = useLocalStorageState(
+ COLUMNS_ORDER_KEY,
+ {
+ defaultValue: [],
+ },
+ );
+
+ const [columnsWidth, setColumnsWidth] = useLocalStorageState<
+ Record
+ >(COLUMNS_WIDTH_KEY, {
+ defaultValue: {},
+ });
+
+ const columns = useMemo(() => {
+ const retVal = convertColumnDataToColumn(
+ DEFAULT_COLUMNS,
+ {
+ columnsOrder,
+ columnsWidth,
+ selectedColumns,
+ },
+ );
+
+ retVal.push({
+ id: "actions",
+ enableHiding: false,
+ cell: PromptRowActionsCell,
+ size: 48,
+ enableResizing: false,
+ });
+
+ return retVal;
+ }, [selectedColumns, columnsWidth, columnsOrder]);
+
+ const resizeConfig = useMemo(
+ () => ({
+ enabled: true,
+ onColumnResize: setColumnsWidth,
+ }),
+ [setColumnsWidth],
+ );
+
+ const handleNewDatasetClick = useCallback(() => {
+ setOpenDialog(true);
+ resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
+ }, []);
+
+ const handleRowClick = useCallback(
+ (prompt: Prompt) => {
+ // ALEX
+ // navigate({
+ // to: "/$workspaceName/prompts/$promptId/items",
+ // params: {
+ // promptId: prompt.id,
+ // workspaceName,
+ // },
+ // });
+ },
+ [navigate, workspaceName],
+ );
+
+ if (isPending) {
+ return ;
+ }
+
+ return (
+
+
+
Prompts
+
+
+
+
+
+
+
+
+
+ {noData && (
+
+ )}
+
+ }
+ />
+
+
+
+
+
+ );
+};
+
+export default PromptsPage;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
new file mode 100644
index 000000000..70285fc37
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+import { CellContext } from "@tanstack/react-table";
+import { Tag } from "@/components/ui/tag";
+import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
+import {ArrowUpRight} from "lucide-react";
+import {Prompt} from "@/types/prompts";
+
+
+const TagNameCell = (context: CellContext) => {
+ const value = context.getValue();
+
+ return (
+
+
+ {value}
+
+
+
+ );
+};
+
+export default TagNameCell;
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index 0ad731447..b5deff74c 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -22,6 +22,7 @@ import ProjectPage from "@/components/pages/ProjectPage/ProjectPage";
import ProjectsPage from "@/components/pages/ProjectsPage/ProjectsPage";
import TracesPage from "@/components/pages/TracesPage/TracesPage";
import WorkspacePage from "@/components/pages/WorkspacePage/WorkspacePage";
+import PromptsPage from "@/components/pages/PromptsPage/PromptsPage";
const TanStackRouterDevtools =
process.env.NODE_ENV === "production"
@@ -184,6 +185,21 @@ const datasetItemsRoute = createRoute({
},
});
+// ----------- prompts
+const promptsRoute = createRoute({
+ path: "/prompts",
+ getParentRoute: () => workspaceRoute,
+ staticData: {
+ title: "Prompts",
+ },
+});
+
+const promptsListRoute = createRoute({
+ path: "/",
+ getParentRoute: () => promptsRoute,
+ component: PromptsPage,
+});
+
const routeTree = rootRoute.addChildren([
workspaceGuardPartialLayoutRoute.addChildren([
getStartedRoute,
@@ -205,6 +221,9 @@ const routeTree = rootRoute.addChildren([
datasetsListRoute,
datasetRoute.addChildren([datasetItemsRoute]),
]),
+ promptsRoute.addChildren([
+ promptsListRoute,
+ ])
]),
]),
]);
diff --git a/apps/opik-frontend/src/types/prompts.ts b/apps/opik-frontend/src/types/prompts.ts
new file mode 100644
index 000000000..ee174ddbd
--- /dev/null
+++ b/apps/opik-frontend/src/types/prompts.ts
@@ -0,0 +1,8 @@
+export interface Prompt {
+ id: string;
+ name: string;
+ description: string;
+ last_updated_at: string;
+ created_at: string;
+ versions_count: number;
+}
From 196b26475c02cd0b7cbf05dac8d257ba29a6988c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:47:05 +0100
Subject: [PATCH 02/45] [OPIK-347]: removed unused vars;
---
apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts | 2 +-
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
index dc01359e9..ca57ddf28 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -24,7 +24,7 @@ const usePromptCreateMutation = () => {
prompt,
workspaceName,
}: UsePromptCreateMutationParams) => {
- const { data, headers } = await api.post(PROMPTS_REST_ENDPOINT, {
+ const { data } = await api.post(PROMPTS_REST_ENDPOINT, {
...prompt,
workspace_name: workspaceName,
});
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index ad83388a2..87dca605c 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -19,8 +19,6 @@ import {Prompt} from "@/types/prompts";
import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
-import ResourceCell from "@/components/shared/DataTableCells/ResourceCell";
-import {RESOURCE_TYPE} from "@/components/shared/ResourceLink/ResourceLink";
const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
const COLUMNS_WIDTH_KEY = "prompts-columns-width";
From fc13e099a5155e7509aa6224ec84d41b6789871a Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:50:24 +0100
Subject: [PATCH 03/45] [OPIK-347]: update the prompt page name;
---
apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx | 2 +-
apps/opik-frontend/src/router.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index a45bcf1db..8848a15c5 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -60,7 +60,7 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
path: "/$workspaceName/prompts",
type: MENU_ITEM_TYPE.router,
icon: FileTerminal,
- label: "Prompts",
+ label: "Prompts library",
count: "prompts",
},
{
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index b5deff74c..93e83ba52 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -190,7 +190,7 @@ const promptsRoute = createRoute({
path: "/prompts",
getParentRoute: () => workspaceRoute,
staticData: {
- title: "Prompts",
+ title: "Prompts library",
},
});
From 8899bbe0ab14b5b693f06097500da854a502c4d1 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:51:47 +0100
Subject: [PATCH 04/45] [OPIK-347]: update the prompt page name;
---
apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx | 2 +-
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 +-
apps/opik-frontend/src/router.tsx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 8848a15c5..5bedbd1ec 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -60,7 +60,7 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
path: "/$workspaceName/prompts",
type: MENU_ITEM_TYPE.router,
icon: FileTerminal,
- label: "Prompts library",
+ label: "Prompt library",
count: "prompts",
},
{
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 87dca605c..ff700ce97 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -167,7 +167,7 @@ const PromptsPage: React.FunctionComponent = () => {
return (
-
Prompts
+ Prompt library
workspaceRoute,
staticData: {
- title: "Prompts library",
+ title: "Prompt library",
},
});
From f9eaca1ba26878658e27c08ace5121d11da6297c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:02:03 +0100
Subject: [PATCH 05/45] [OPIK-347]: eslint error fixes;
---
apps/opik-frontend/src/api/api.ts | 1 -
.../api/prompts/usePromptCreateMutation.ts | 4 +-
.../api/prompts/usePromptDeleteMutation.ts | 2 +-
.../src/api/prompts/usePromptsList.ts | 165 +++++++++---------
.../src/components/layout/SideBar/SideBar.tsx | 4 +-
.../pages/PromptsPage/AddPromptDialog.tsx | 18 +-
.../PromptsPage/PromptRowActionsCell.tsx | 3 +-
.../pages/PromptsPage/PromptsPage.tsx | 42 ++---
.../pages/PromptsPage/TagNameCell.tsx | 5 +-
apps/opik-frontend/src/router.tsx | 4 +-
10 files changed, 122 insertions(+), 126 deletions(-)
diff --git a/apps/opik-frontend/src/api/api.ts b/apps/opik-frontend/src/api/api.ts
index 34e94eb11..486d296aa 100644
--- a/apps/opik-frontend/src/api/api.ts
+++ b/apps/opik-frontend/src/api/api.ts
@@ -17,7 +17,6 @@ export const TRACES_REST_ENDPOINT = "/v1/private/traces/";
export const SPANS_REST_ENDPOINT = "/v1/private/spans/";
export const PROMPTS_REST_ENDPOINT = "/v1/private/prompts/";
-
export type QueryConfig = Omit<
UseQueryOptions<
TQueryFnData,
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
index ca57ddf28..4ed9e2d63 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -2,9 +2,9 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import get from "lodash/get";
-import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
import { useToast } from "@/components/ui/use-toast";
-import {Prompt} from "@/types/prompts";
+import { Prompt } from "@/types/prompts";
interface CreatePromptTemplate {
template: string;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
index 509a31008..b60bc6428 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
@@ -1,7 +1,7 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import get from "lodash/get";
import { useToast } from "@/components/ui/use-toast";
-import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
type UsePromptDeleteMutationParams = {
promptId: string;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 9007f2769..45c8f9a22 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -1,6 +1,6 @@
import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
-import api, {PROMPTS_REST_ENDPOINT, QueryConfig} from "@/api/api";
-import {Prompt} from "@/types/prompts";
+import { QueryConfig } from "@/api/api";
+import { Prompt } from "@/types/prompts";
type UsePromptsListParams = {
workspaceName: string;
@@ -17,107 +17,106 @@ type UsePromptsListResponse = {
// ALEX
const FAKE_PROMPTS: Prompt[] = [
{
- "id": "4338ec03-6ee9-4635-b071-77849626b948",
- "name": "Item 1123421342134341234812349123841239048132094812304123804301294",
- "description": "This is a description for Item 1.",
- "last_updated_at": "2022-04-15 00:00:00",
- "created_at": "2020-09-09 00:00:00",
- "versions_count": 6
+ id: "4338ec03-6ee9-4635-b071-77849626b948",
+ name: "Item 1123421342134341234812349123841239048132094812304123804301294",
+ description: "This is a description for Item 1.",
+ last_updated_at: "2022-04-15 00:00:00",
+ created_at: "2020-09-09 00:00:00",
+ versions_count: 6,
},
{
- "id": "2ac76571-520f-4664-9ad5-1439492ad557",
- "name": "Item 2",
- "description": "This is a description for Item 2.",
- "last_updated_at": "2022-08-19 00:00:00",
- "created_at": "2021-10-27 00:00:00",
- "versions_count": 4
+ id: "2ac76571-520f-4664-9ad5-1439492ad557",
+ name: "Item 2",
+ description: "This is a description for Item 2.",
+ last_updated_at: "2022-08-19 00:00:00",
+ created_at: "2021-10-27 00:00:00",
+ versions_count: 4,
},
{
- "id": "3ba74f16-698f-4318-9427-d26403bc117b",
- "name": "Item 3",
- "description": "This is a description for Item 3.",
- "last_updated_at": "2023-12-12 00:00:00",
- "created_at": "2021-10-08 00:00:00",
- "versions_count": 5
+ id: "3ba74f16-698f-4318-9427-d26403bc117b",
+ name: "Item 3",
+ description: "This is a description for Item 3.",
+ last_updated_at: "2023-12-12 00:00:00",
+ created_at: "2021-10-08 00:00:00",
+ versions_count: 5,
},
{
- "id": "bbef9b6c-d991-4132-9c08-24e1584ccea2",
- "name": "Item 4",
- "description": "This is a description for Item 4.",
- "last_updated_at": "2023-05-14 00:00:00",
- "created_at": "2023-01-04 00:00:00",
- "versions_count": 10
+ id: "bbef9b6c-d991-4132-9c08-24e1584ccea2",
+ name: "Item 4",
+ description: "This is a description for Item 4.",
+ last_updated_at: "2023-05-14 00:00:00",
+ created_at: "2023-01-04 00:00:00",
+ versions_count: 10,
},
{
- "id": "57c82e2b-3d75-4f16-87ac-3201554ea84d",
- "name": "Item 5",
- "description": "This is a description for Item 5.",
- "last_updated_at": "2022-06-10 00:00:00",
- "created_at": "2021-10-06 00:00:00",
- "versions_count": 4
+ id: "57c82e2b-3d75-4f16-87ac-3201554ea84d",
+ name: "Item 5",
+ description: "This is a description for Item 5.",
+ last_updated_at: "2022-06-10 00:00:00",
+ created_at: "2021-10-06 00:00:00",
+ versions_count: 4,
},
{
- "id": "caad2d07-6be4-4e30-8e54-45928c4c675c",
- "name": "Item 6",
- "description": "This is a description for Item 6.",
- "last_updated_at": "2023-11-07 00:00:00",
- "created_at": "2022-04-26 00:00:00",
- "versions_count": 7
+ id: "caad2d07-6be4-4e30-8e54-45928c4c675c",
+ name: "Item 6",
+ description: "This is a description for Item 6.",
+ last_updated_at: "2023-11-07 00:00:00",
+ created_at: "2022-04-26 00:00:00",
+ versions_count: 7,
},
{
- "id": "955439b8-2199-4edb-bfff-0becef27f477",
- "name": "Item 7",
- "description": "This is a description for Item 7.",
- "last_updated_at": "2023-09-21 00:00:00",
- "created_at": "2023-08-15 00:00:00",
- "versions_count": 5
+ id: "955439b8-2199-4edb-bfff-0becef27f477",
+ name: "Item 7",
+ description: "This is a description for Item 7.",
+ last_updated_at: "2023-09-21 00:00:00",
+ created_at: "2023-08-15 00:00:00",
+ versions_count: 5,
},
{
- "id": "059452b9-9050-4b99-893f-8e809adae877",
- "name": "Item 8",
- "description": "This is a description for Item 8.",
- "last_updated_at": "2023-04-10 00:00:00",
- "created_at": "2022-09-22 00:00:00",
- "versions_count": 8
+ id: "059452b9-9050-4b99-893f-8e809adae877",
+ name: "Item 8",
+ description: "This is a description for Item 8.",
+ last_updated_at: "2023-04-10 00:00:00",
+ created_at: "2022-09-22 00:00:00",
+ versions_count: 8,
},
{
- "id": "c46f907a-7e35-4d35-a482-fb4a7fee3967",
- "name": "Item 9",
- "description": "This is a description for Item 9.",
- "last_updated_at": "2023-12-22 00:00:00",
- "created_at": "2023-05-13 00:00:00",
- "versions_count": 8
+ id: "c46f907a-7e35-4d35-a482-fb4a7fee3967",
+ name: "Item 9",
+ description: "This is a description for Item 9.",
+ last_updated_at: "2023-12-22 00:00:00",
+ created_at: "2023-05-13 00:00:00",
+ versions_count: 8,
},
{
- "id": "c4365771-f654-4434-9272-8e22f623906b",
- "name": "Item 10",
- "description": "This is a description for Item 10.",
- "last_updated_at": "2023-09-09 00:00:00",
- "created_at": "2022-12-02 00:00:00",
- "versions_count": 6
- }
-]
-
+ id: "c4365771-f654-4434-9272-8e22f623906b",
+ name: "Item 10",
+ description: "This is a description for Item 10.",
+ last_updated_at: "2023-09-09 00:00:00",
+ created_at: "2022-12-02 00:00:00",
+ versions_count: 6,
+ },
+];
-const getPromptsList = async (
- { signal }: QueryFunctionContext,
- { workspaceName, search, size, page }: UsePromptsListParams,
-) => {
- // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
- // signal,
- // params: {
- // workspace_name: workspaceName,
- // ...(search && { name: search }),
- // size,
- // page,
- // },
- // });
+const getPromptsList = async () =>
+ // { signal }: QueryFunctionContext,
+ // { workspaceName, search, size, page }: UsePromptsListParams,
+ {
+ // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
+ // signal,
+ // params: {
+ // workspace_name: workspaceName,
+ // ...(search && { name: search }),
+ // size,
+ // page,
+ // },
+ // });
- return {
- content: FAKE_PROMPTS,
- total: FAKE_PROMPTS.length,
+ return {
+ content: FAKE_PROMPTS,
+ total: FAKE_PROMPTS.length,
+ };
};
-};
export default function usePromptsList(
params: UsePromptsListParams,
@@ -125,7 +124,7 @@ export default function usePromptsList(
) {
return useQuery({
queryKey: ["prompts", params],
- queryFn: (context) => getPromptsList(context, params),
+ queryFn: (context) => getPromptsList(),
...options,
});
}
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 5bedbd1ec..1bd7b916f 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -11,7 +11,7 @@ import {
MessageSquare,
PanelLeftClose,
MessageCircleQuestion,
- FileTerminal
+ FileTerminal,
} from "lucide-react";
import { keepPreviousData } from "@tanstack/react-query";
@@ -231,7 +231,7 @@ const SideBar: React.FunctionComponent = ({
datasets: datasetsData?.total,
experiments: experimentsData?.total,
feedbackDefinitions: feedbackDefinitions?.total,
- prompts: promptsData?.total
+ prompts: promptsData?.total,
};
const bottomMenuItems: MenuItem[] = [
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
index 437497c60..671b8f8d0 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useState} from "react";
+import React, { useCallback, useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -13,8 +13,13 @@ import { Label } from "@/components/ui/label";
import useAppStore from "@/store/AppStore";
import { Textarea } from "@/components/ui/textarea";
import usePromptCreateMutation from "@/api/prompts/usePromptCreateMutation";
-import {Prompt} from "@/types/prompts";
-import {AccordionContent, AccordionItem, AccordionTrigger, Accordion} from "@/components/ui/accordion";
+import { Prompt } from "@/types/prompts";
+import {
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+ Accordion,
+} from "@/components/ui/accordion";
type AddPromptDialogProps = {
open: boolean;
@@ -74,9 +79,12 @@ const AddPromptDialog: React.FunctionComponent = ({
value={prompt}
onChange={(event) => setPrompt(event.target.value)}
/>
- You can specify variables using the "mustache" syntax: {"{{variable}}"}.
+
+ You can specify variables using the "mustache" syntax:{" "}
+ {"{{variable}}"}.
+
-
+
Description
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
index 3f77a0793..ac77ad530 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
@@ -9,7 +9,7 @@ import { MoreHorizontal, Trash } from "lucide-react";
import React, { useCallback, useRef, useState } from "react";
import { CellContext } from "@tanstack/react-table";
import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
-import {Prompt} from "@/types/prompts";
+import { Prompt } from "@/types/prompts";
import usePromptDeleteMutation from "@/api/prompts/usePromptDeleteMutation";
export const PromptRowActionsCell: React.FunctionComponent<
@@ -59,7 +59,6 @@ export const PromptRowActionsCell: React.FunctionComponent<
Delete
-
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index ff700ce97..550dedd9a 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -15,8 +15,8 @@ import useLocalStorageState from "use-local-storage-state";
import { convertColumnDataToColumn } from "@/lib/table";
import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
import usePromptsList from "@/api/prompts/usePromptsList";
-import {Prompt} from "@/types/prompts";
-import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
+import { Prompt } from "@/types/prompts";
+import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
@@ -39,7 +39,7 @@ export const DEFAULT_COLUMNS: ColumnData
[] = [
id: "name",
label: "Name",
type: COLUMN_TYPE.string,
- cell: TagNameCell as never
+ cell: TagNameCell as never,
},
{
id: "versions_count",
@@ -113,14 +113,11 @@ const PromptsPage: React.FunctionComponent = () => {
});
const columns = useMemo(() => {
- const retVal = convertColumnDataToColumn(
- DEFAULT_COLUMNS,
- {
- columnsOrder,
- columnsWidth,
- selectedColumns,
- },
- );
+ const retVal = convertColumnDataToColumn(DEFAULT_COLUMNS, {
+ columnsOrder,
+ columnsWidth,
+ selectedColumns,
+ });
retVal.push({
id: "actions",
@@ -146,19 +143,16 @@ const PromptsPage: React.FunctionComponent = () => {
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
- const handleRowClick = useCallback(
- (prompt: Prompt) => {
- // ALEX
- // navigate({
- // to: "/$workspaceName/prompts/$promptId/items",
- // params: {
- // promptId: prompt.id,
- // workspaceName,
- // },
- // });
- },
- [navigate, workspaceName],
- );
+ const handleRowClick = useCallback(() => {
+ // ALEX
+ // navigate({
+ // to: "/$workspaceName/prompts/$promptId/items",
+ // params: {
+ // promptId: prompt.id,
+ // workspaceName,
+ // },
+ // });
+ }, [navigate, workspaceName]);
if (isPending) {
return ;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
index 70285fc37..066421fde 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
@@ -2,9 +2,8 @@ import React from "react";
import { CellContext } from "@tanstack/react-table";
import { Tag } from "@/components/ui/tag";
import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
-import {ArrowUpRight} from "lucide-react";
-import {Prompt} from "@/types/prompts";
-
+import { ArrowUpRight } from "lucide-react";
+import { Prompt } from "@/types/prompts";
const TagNameCell = (context: CellContext) => {
const value = context.getValue();
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index 498e2ae27..607ba067e 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -221,9 +221,7 @@ const routeTree = rootRoute.addChildren([
datasetsListRoute,
datasetRoute.addChildren([datasetItemsRoute]),
]),
- promptsRoute.addChildren([
- promptsListRoute,
- ])
+ promptsRoute.addChildren([promptsListRoute]),
]),
]),
]);
From c01f49ca2cdb954555bcf9dd5816fec33a117eac Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:02:26 +0100
Subject: [PATCH 06/45] [OPIK-347]: eslint error fixes;
---
apps/opik-frontend/src/api/prompts/usePromptsList.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 45c8f9a22..1cac9fdde 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -1,4 +1,4 @@
-import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import { useQuery } from "@tanstack/react-query";
import { QueryConfig } from "@/api/api";
import { Prompt } from "@/types/prompts";
@@ -124,7 +124,7 @@ export default function usePromptsList(
) {
return useQuery({
queryKey: ["prompts", params],
- queryFn: (context) => getPromptsList(),
+ queryFn: () => getPromptsList(),
...options,
});
}
From 94d58cf97a12ed2be968f33cd0673887973b4a00 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:04:31 +0100
Subject: [PATCH 07/45] [OPIK-347]: remove not needed dependencies from the
usecallback;
---
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 550dedd9a..68ff60d30 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -152,7 +152,7 @@ const PromptsPage: React.FunctionComponent = () => {
// workspaceName,
// },
// });
- }, [navigate, workspaceName]);
+ }, []);
if (isPending) {
return ;
From c4e9f02a2fba81baad8b03e978a52be8da72168e Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:06:21 +0100
Subject: [PATCH 08/45] [OPIK-347]: remove navigate;
---
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 68ff60d30..fc23f9753 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -1,5 +1,4 @@
import React, { useCallback, useMemo, useRef, useState } from "react";
-import { useNavigate } from "@tanstack/react-router";
import { keepPreviousData } from "@tanstack/react-query";
import DataTable from "@/components/shared/DataTable/DataTable";
import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
@@ -67,7 +66,6 @@ export const DEFAULT_SELECTED_COLUMNS: string[] = [
];
const PromptsPage: React.FunctionComponent = () => {
- const navigate = useNavigate();
const workspaceName = useAppStore((state) => state.activeWorkspaceName);
const resetDialogKeyRef = useRef(0);
From afd030224734fcae78b180ead3f1a000af5201f5 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Tue, 5 Nov 2024 14:45:18 +0100
Subject: [PATCH 09/45] [OPIK-349]: add a prompt tab;
---
.../prompts/useCreatePromptVersionMutation.ts | 49 ++++++++++
.../src/api/prompts/usePromptById.ts | 52 +++++++++++
.../src/api/prompts/usePromptsVersionsById.ts | 93 +++++++++++++++++++
.../CompareExperimentsDetails.tsx | 12 +--
.../pages/PromptPage/PromptPage.tsx | 70 ++++++++++++++
.../PromptPage/PromptTab/CommitHistory.tsx | 62 +++++++++++++
.../PromptPage/PromptTab/EditPromptDialog.tsx | 75 +++++++++++++++
.../pages/PromptPage/PromptTab/PromptTab.tsx | 90 ++++++++++++++++++
.../PromptTab/UseThisPromptDialog.tsx | 31 +++++++
.../pages/PromptsPage/PromptsPage.tsx | 20 ++--
.../src/components/shared/DateTag/DateTag.tsx | 21 +++++
.../TraceAnnotateViewer/AnnotateRow.tsx | 6 +-
.../src/components/ui/button.tsx | 1 +
.../src/hooks/usePromptIdFromURL.ts | 8 ++
apps/opik-frontend/src/router.tsx | 12 ++-
apps/opik-frontend/src/types/prompts.ts | 17 ++++
16 files changed, 594 insertions(+), 25 deletions(-)
create mode 100644 apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptById.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
create mode 100644 apps/opik-frontend/src/hooks/usePromptIdFromURL.ts
diff --git a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
new file mode 100644
index 000000000..a93333f04
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
@@ -0,0 +1,49 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { AxiosError } from "axios";
+import get from "lodash/get";
+
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
+import { useToast } from "@/components/ui/use-toast";
+
+type UseCreatePromptVersionMutationParams = {
+ name: string;
+ id: string;
+ template: string;
+};
+
+const useCreatePromptVersionMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({
+ name,
+ id,
+ template,
+ }: UseCreatePromptVersionMutationParams) => {
+ const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}/versions`, {
+ ...prompt,
+ });
+
+ return data;
+ },
+ onError: (error: AxiosError) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: (data, error, variables, context) => {
+ return queryClient.invalidateQueries({ queryKey: ["prompt-versions"] });
+ },
+ });
+};
+
+export default useCreatePromptVersionMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptById.ts b/apps/opik-frontend/src/api/prompts/usePromptById.ts
new file mode 100644
index 000000000..818a86aa9
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptById.ts
@@ -0,0 +1,52 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
+import { PromptWithLatestVersion } from "@/types/prompts";
+
+// ALEX
+const FAKE_PROMPT = {
+ id: "p001",
+ name: "Product Recommendation Prompt",
+ description:
+ "A prompt designed to generate product recommendations based on user preferences.",
+ last_updated_at: "2024-11-04T14:35:00Z",
+ created_at: "2024-10-20T09:00:00Z",
+ versions_count: 3,
+
+ latest_version: {
+ id: "v003",
+ created_at: "2024-11-04T14:35:00Z",
+ template:
+ "Recommend products to {{username}} based on preferences in {{category}} and previous interactions.",
+ variables: ["username", "category"],
+ },
+};
+
+const getPromptById = async (
+ { signal }: QueryFunctionContext,
+ { promptId }: UsePromptByIdParams,
+) => {
+ try {
+ const { data } = await api.get(`${PROMPTS_REST_ENDPOINT}/${promptId}`, {
+ signal,
+ });
+
+ return data;
+ } catch {
+ return FAKE_PROMPT;
+ }
+};
+
+type UsePromptByIdParams = {
+ promptId: string;
+};
+
+export default function usePromptById(
+ params: UsePromptByIdParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompt", params],
+ queryFn: (context) => getPromptById(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts b/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
new file mode 100644
index 000000000..99ccdbec4
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
@@ -0,0 +1,93 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
+import { CompactPromptVersion } from "@/types/prompts";
+
+// ALEX
+const FAKE_PROMPT_VERSIONS: CompactPromptVersion[] = [
+ {
+ id: "prompt_1234123412341234123412341241231",
+ created_at: "2023-10-01T08:30:00Z",
+ },
+ {
+ id: "prompt_2",
+ created_at: "2023-10-02T10:15:00Z",
+ },
+ {
+ id: "prompt_3",
+ created_at: "2023-10-03T12:45:00Z",
+ },
+ {
+ id: "prompt_4",
+ created_at: "2023-10-04T15:20:00Z",
+ },
+ {
+ id: "prompt_5",
+ created_at: "2023-10-05T18:05:00Z",
+ },
+ {
+ id: "prompt_6",
+ created_at: "2023-10-06T09:40:00Z",
+ },
+ {
+ id: "prompt_7",
+ created_at: "2023-10-07T11:25:00Z",
+ },
+ {
+ id: "prompt_8",
+ created_at: "2023-10-08T13:55:00Z",
+ },
+ {
+ id: "prompt_9",
+ created_at: "2023-10-09T16:10:00Z",
+ },
+ {
+ id: "prompt_10",
+ created_at: "2023-10-10T19:30:00Z",
+ },
+];
+
+const getPromptVersionsById = async (
+ { signal }: QueryFunctionContext,
+ { promptId, size, page, search }: UsePromptVersionsByIdParams,
+) => {
+ try {
+ const { data } = await api.get(
+ `${PROMPTS_REST_ENDPOINT}/${promptId}/versions`,
+ {
+ signal,
+ params: {
+ ...(search && { name: search }),
+ size,
+ page,
+ },
+ },
+ );
+
+ return data;
+ } catch {
+ return { content: FAKE_PROMPT_VERSIONS };
+ }
+};
+
+type UsePromptVersionsByIdParams = {
+ promptId: string;
+ search?: string;
+ page: number;
+ size: number;
+};
+
+type UsePromptsVersionsByIdResponse = {
+ content: CompactPromptVersion[];
+ total: number;
+};
+
+export default function usePromptVersionsById(
+ params: UsePromptVersionsByIdParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompt-versions", params],
+ queryFn: (context) => getPromptVersionsById(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
index 2d3f87aad..693766cc4 100644
--- a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
+++ b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
@@ -21,6 +21,7 @@ import { Button } from "@/components/ui/button";
import ResourceLink, {
RESOURCE_TYPE,
} from "@/components/shared/ResourceLink/ResourceLink";
+import DateTag from "@/components/shared/DateTag/DateTag";
type CompareExperimentsDetailsProps = {
experimentsIds: string[];
@@ -201,16 +202,7 @@ const CompareExperimentsDetails: React.FunctionComponent<
{renderCompareFeedbackScoresButton()}
- {!isCompare && (
-
-
- {formatDate(experiment?.created_at)}
-
- )}
+ {!isCompare &&
}
{
+ const [tab, setTab] = useQueryParam("tab", StringParam, {
+ updateType: "replaceIn",
+ });
+
+ const promptId = usePromptIdFromURL();
+
+ const { data: prompt } = usePromptById({ promptId }, { enabled: !!promptId });
+ const promptName = prompt?.name || "";
+ const setBreadcrumbParam = useBreadcrumbsStore((state) => state.setParam);
+
+ useEffect(() => {
+ if (promptId && promptName) {
+ setBreadcrumbParam("promptId", promptId, promptName);
+ }
+ }, [promptId, promptName]);
+
+ useEffect(() => {
+ if (!tab) {
+ setTab("prompt");
+ }
+ }, [tab]);
+
+ return (
+
+
+
+
{promptName}
+
+
+ {prompt?.created_at && (
+
+
+
+ )}
+
+
+
+
+
+ Prompt
+
+
+ Experiments
+
+
+ Commits
+
+
+
+
+
+ Experiments
+ Commits
+
+
+ );
+};
+
+export default PromptPage;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
new file mode 100644
index 000000000..b3ff6dfc5
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -0,0 +1,62 @@
+import { Copy, GitCommitVertical } from "lucide-react";
+import copy from "clipboard-copy";
+
+import { formatDate } from "@/lib/date";
+import React, { useState } from "react";
+import { CompactPromptVersion } from "@/types/prompts";
+import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
+import { Button } from "@/components/ui/button";
+import { useToast } from "@/components/ui/use-toast";
+
+interface CommitHistoryProps {
+ versions: CompactPromptVersion[];
+}
+
+const CommitHistory = ({ versions }: CommitHistoryProps) => {
+ const { toast } = useToast();
+ const [hoveredVersionId, setHoveredVersionId] = useState(null);
+
+ const handleCopyClick = async (versionId: string) => {
+ await copy(versionId);
+
+ toast({
+ description: "ID successfully copied to clipboard",
+ });
+ };
+
+ return (
+
+ );
+};
+
+export default CommitHistory;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
new file mode 100644
index 000000000..1624d29c1
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -0,0 +1,75 @@
+import React, { useState } from "react";
+
+import {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Textarea } from "@/components/ui/textarea";
+import { Label } from "@/components/ui/label";
+import { Button } from "@/components/ui/button";
+
+type EditPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+
+ promptTemplate: string;
+ promptId: string;
+};
+
+const EditPromptDialog: React.FunctionComponent = ({
+ open,
+ setOpen,
+ promptTemplate: parentPromptTemplate,
+}) => {
+ const [promptTemplate, setPromptTemplate] = useState(parentPromptTemplate);
+
+ const isValid =
+ promptTemplate?.length && promptTemplate !== parentPromptTemplate;
+
+ return (
+
+ );
+};
+
+export default EditPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
new file mode 100644
index 000000000..293b49ce2
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -0,0 +1,90 @@
+import React, { useMemo, useRef, useState } from "react";
+
+import { Button } from "@/components/ui/button";
+import { Info, Pencil } from "lucide-react";
+import { PromptWithLatestVersion } from "@/types/prompts";
+import Loader from "@/components/shared/Loader/Loader";
+import usePromptVersionsById from "@/api/prompts/usePromptsVersionsById";
+import UseThisPromptDialog from "@/components/pages/PromptPage/PromptTab/UseThisPromptDialog";
+import EditPromptDialog from "@/components/pages/PromptPage/PromptTab/EditPromptDialog";
+import CommitHistory from "@/components/pages/PromptPage/PromptTab/CommitHistory";
+
+interface PromptTabInterface {
+ prompt?: PromptWithLatestVersion;
+}
+
+const PromptTab = ({ prompt }: PromptTabInterface) => {
+ const [openUseThisPrompt, setOpenUseThisPrompt] = useState(false);
+ const [openEditPrompt, setOpenEditPrompt] = useState(false);
+ const editPromptResetKeyRef = useRef(0);
+ const { data } = usePromptVersionsById(
+ {
+ promptId: prompt?.id || "",
+ page: 1,
+ size: 25,
+ },
+ {
+ enabled: !!prompt?.id,
+ },
+ );
+
+ const versions = data?.content;
+
+ const handleOpenEditPrompt = (value: boolean) => {
+ editPromptResetKeyRef.current += 1;
+ setOpenEditPrompt(value);
+ };
+
+ if (!prompt) {
+ return ;
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
Prompt
+
+ {prompt?.latest_version?.template}
+
+
+
+
+ Commit history
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default PromptTab;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
new file mode 100644
index 000000000..cb0f97866
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
@@ -0,0 +1,31 @@
+import React from "react";
+
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+
+type UseThisPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+};
+
+const UseThisPromptDialog: React.FunctionComponent<
+ UseThisPromptDialogProps
+> = ({ open, setOpen }) => {
+ return (
+
+ );
+};
+
+export default UseThisPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index fc23f9753..64c7654d7 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -18,6 +18,7 @@ import { Prompt } from "@/types/prompts";
import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
+import { useNavigate } from "@tanstack/react-router";
const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
const COLUMNS_WIDTH_KEY = "prompts-columns-width";
@@ -66,6 +67,8 @@ export const DEFAULT_SELECTED_COLUMNS: string[] = [
];
const PromptsPage: React.FunctionComponent = () => {
+ const navigate = useNavigate();
+
const workspaceName = useAppStore((state) => state.activeWorkspaceName);
const resetDialogKeyRef = useRef(0);
@@ -141,15 +144,14 @@ const PromptsPage: React.FunctionComponent = () => {
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
- const handleRowClick = useCallback(() => {
- // ALEX
- // navigate({
- // to: "/$workspaceName/prompts/$promptId/items",
- // params: {
- // promptId: prompt.id,
- // workspaceName,
- // },
- // });
+ const handleRowClick = useCallback((prompt: Prompt) => {
+ navigate({
+ to: "/$workspaceName/prompts/$promptId",
+ params: {
+ promptId: prompt.id,
+ workspaceName,
+ },
+ });
}, []);
if (isPending) {
diff --git a/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx b/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
new file mode 100644
index 000000000..17f39b202
--- /dev/null
+++ b/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
@@ -0,0 +1,21 @@
+import { Clock } from "lucide-react";
+import { formatDate } from "@/lib/date";
+import { Tag } from "@/components/ui/tag";
+import React from "react";
+
+interface DateTagProps {
+ date: string;
+}
+
+const DateTag = ({ date }: DateTagProps) => {
+ return (
+
+
+ {formatDate(date)}
+
+ );
+};
+
+DateTag.displayName = "DateTag";
+
+export default DateTag;
diff --git a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
index 13ba41608..195c78b0a 100644
--- a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
+++ b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
@@ -167,11 +167,7 @@ const AnnotateRow: React.FunctionComponent = ({
{!isUndefined(feedbackScore?.value) && (
-
@@ -191,7 +191,7 @@ const PromptsPage: React.FunctionComponent = () => {
noData={
{noData && (
-
+
Create new prompt
)}
From 307d6522a6b42f801265f4180b3c9b4fec5d6d75 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 10:44:01 +0100
Subject: [PATCH 12/45] [OPIK-351]: add a pending state to commits;
---
.../components/pages/PromptPage/PromptTab/CommitsTab.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
index d490c66f4..d12e7e856 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo, useState } from "react";
+import React, { useCallback, useState } from "react";
import { CompactPromptVersion, PromptWithLatestVersion } from "@/types/prompts";
import Loader from "@/components/shared/Loader/Loader";
@@ -56,7 +56,7 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
- const { data } = usePromptVersionsById(
+ const { data, isPending } = usePromptVersionsById(
{
promptId: prompt?.id || "",
page: page,
@@ -81,7 +81,7 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
});
}, []);
- if (!versions) {
+ if (isPending) {
return ;
}
From 56295c0f8b8d4fc9048d24dc4e411cddb18aaf58 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:46:12 +0100
Subject: [PATCH 13/45] [OPIK-347]: add a prompts list page with fake data;
---
apps/opik-frontend/src/api/api.ts | 2 +
.../api/prompts/usePromptCreateMutation.ts | 60 +++++
.../api/prompts/usePromptDeleteMutation.ts | 38 +++
.../src/api/prompts/usePromptsList.ts | 131 ++++++++++
.../src/components/layout/SideBar/SideBar.tsx | 23 ++
.../pages/PromptsPage/AddPromptDialog.tsx | 110 +++++++++
.../PromptsPage/PromptRowActionsCell.tsx | 67 ++++++
.../pages/PromptsPage/PromptsPage.tsx | 227 ++++++++++++++++++
.../pages/PromptsPage/TagNameCell.tsx | 25 ++
apps/opik-frontend/src/router.tsx | 19 ++
apps/opik-frontend/src/types/prompts.ts | 8 +
11 files changed, 710 insertions(+)
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptsList.ts
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
create mode 100644 apps/opik-frontend/src/types/prompts.ts
diff --git a/apps/opik-frontend/src/api/api.ts b/apps/opik-frontend/src/api/api.ts
index 10ad7e277..34e94eb11 100644
--- a/apps/opik-frontend/src/api/api.ts
+++ b/apps/opik-frontend/src/api/api.ts
@@ -15,6 +15,8 @@ export const FEEDBACK_DEFINITIONS_REST_ENDPOINT =
"/v1/private/feedback-definitions/";
export const TRACES_REST_ENDPOINT = "/v1/private/traces/";
export const SPANS_REST_ENDPOINT = "/v1/private/spans/";
+export const PROMPTS_REST_ENDPOINT = "/v1/private/prompts/";
+
export type QueryConfig = Omit<
UseQueryOptions<
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
new file mode 100644
index 000000000..dc01359e9
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -0,0 +1,60 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { AxiosError } from "axios";
+import get from "lodash/get";
+
+import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import { useToast } from "@/components/ui/use-toast";
+import {Prompt} from "@/types/prompts";
+
+interface CreatePromptTemplate {
+ template: string;
+}
+
+type UsePromptCreateMutationParams = {
+ prompt: Partial & CreatePromptTemplate;
+ workspaceName: string;
+};
+
+const usePromptCreateMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({
+ prompt,
+ workspaceName,
+ }: UsePromptCreateMutationParams) => {
+ const { data, headers } = await api.post(PROMPTS_REST_ENDPOINT, {
+ ...prompt,
+ workspace_name: workspaceName,
+ });
+
+ return data;
+ },
+ onMutate: async (params: UsePromptCreateMutationParams) => {
+ return {
+ queryKey: ["prompts", { workspaceName: params.workspaceName }],
+ };
+ },
+ onError: (error: AxiosError) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: (data, error, variables, context) => {
+ if (context) {
+ return queryClient.invalidateQueries({ queryKey: context.queryKey });
+ }
+ },
+ });
+};
+
+export default usePromptCreateMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
new file mode 100644
index 000000000..509a31008
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
@@ -0,0 +1,38 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import get from "lodash/get";
+import { useToast } from "@/components/ui/use-toast";
+import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+
+type UsePromptDeleteMutationParams = {
+ promptId: string;
+};
+
+const usePromptDeleteMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({ promptId }: UsePromptDeleteMutationParams) => {
+ const { data } = await api.delete(PROMPTS_REST_ENDPOINT + promptId);
+ return data;
+ },
+ onError: (error) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: () => {
+ return queryClient.invalidateQueries({ queryKey: ["prompts"] });
+ },
+ });
+};
+
+export default usePromptDeleteMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
new file mode 100644
index 000000000..9007f2769
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -0,0 +1,131 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, {PROMPTS_REST_ENDPOINT, QueryConfig} from "@/api/api";
+import {Prompt} from "@/types/prompts";
+
+type UsePromptsListParams = {
+ workspaceName: string;
+ search?: string;
+ page: number;
+ size: number;
+};
+
+type UsePromptsListResponse = {
+ content: Prompt[];
+ total: number;
+};
+
+// ALEX
+const FAKE_PROMPTS: Prompt[] = [
+ {
+ "id": "4338ec03-6ee9-4635-b071-77849626b948",
+ "name": "Item 1123421342134341234812349123841239048132094812304123804301294",
+ "description": "This is a description for Item 1.",
+ "last_updated_at": "2022-04-15 00:00:00",
+ "created_at": "2020-09-09 00:00:00",
+ "versions_count": 6
+ },
+ {
+ "id": "2ac76571-520f-4664-9ad5-1439492ad557",
+ "name": "Item 2",
+ "description": "This is a description for Item 2.",
+ "last_updated_at": "2022-08-19 00:00:00",
+ "created_at": "2021-10-27 00:00:00",
+ "versions_count": 4
+ },
+ {
+ "id": "3ba74f16-698f-4318-9427-d26403bc117b",
+ "name": "Item 3",
+ "description": "This is a description for Item 3.",
+ "last_updated_at": "2023-12-12 00:00:00",
+ "created_at": "2021-10-08 00:00:00",
+ "versions_count": 5
+ },
+ {
+ "id": "bbef9b6c-d991-4132-9c08-24e1584ccea2",
+ "name": "Item 4",
+ "description": "This is a description for Item 4.",
+ "last_updated_at": "2023-05-14 00:00:00",
+ "created_at": "2023-01-04 00:00:00",
+ "versions_count": 10
+ },
+ {
+ "id": "57c82e2b-3d75-4f16-87ac-3201554ea84d",
+ "name": "Item 5",
+ "description": "This is a description for Item 5.",
+ "last_updated_at": "2022-06-10 00:00:00",
+ "created_at": "2021-10-06 00:00:00",
+ "versions_count": 4
+ },
+ {
+ "id": "caad2d07-6be4-4e30-8e54-45928c4c675c",
+ "name": "Item 6",
+ "description": "This is a description for Item 6.",
+ "last_updated_at": "2023-11-07 00:00:00",
+ "created_at": "2022-04-26 00:00:00",
+ "versions_count": 7
+ },
+ {
+ "id": "955439b8-2199-4edb-bfff-0becef27f477",
+ "name": "Item 7",
+ "description": "This is a description for Item 7.",
+ "last_updated_at": "2023-09-21 00:00:00",
+ "created_at": "2023-08-15 00:00:00",
+ "versions_count": 5
+ },
+ {
+ "id": "059452b9-9050-4b99-893f-8e809adae877",
+ "name": "Item 8",
+ "description": "This is a description for Item 8.",
+ "last_updated_at": "2023-04-10 00:00:00",
+ "created_at": "2022-09-22 00:00:00",
+ "versions_count": 8
+ },
+ {
+ "id": "c46f907a-7e35-4d35-a482-fb4a7fee3967",
+ "name": "Item 9",
+ "description": "This is a description for Item 9.",
+ "last_updated_at": "2023-12-22 00:00:00",
+ "created_at": "2023-05-13 00:00:00",
+ "versions_count": 8
+ },
+ {
+ "id": "c4365771-f654-4434-9272-8e22f623906b",
+ "name": "Item 10",
+ "description": "This is a description for Item 10.",
+ "last_updated_at": "2023-09-09 00:00:00",
+ "created_at": "2022-12-02 00:00:00",
+ "versions_count": 6
+ }
+]
+
+
+const getPromptsList = async (
+ { signal }: QueryFunctionContext,
+ { workspaceName, search, size, page }: UsePromptsListParams,
+) => {
+ // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
+ // signal,
+ // params: {
+ // workspace_name: workspaceName,
+ // ...(search && { name: search }),
+ // size,
+ // page,
+ // },
+ // });
+
+ return {
+ content: FAKE_PROMPTS,
+ total: FAKE_PROMPTS.length,
+ };
+};
+
+export default function usePromptsList(
+ params: UsePromptsListParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompts", params],
+ queryFn: (context) => getPromptsList(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index e3effc3cd..a45bcf1db 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -11,6 +11,7 @@ import {
MessageSquare,
PanelLeftClose,
MessageCircleQuestion,
+ FileTerminal
} from "lucide-react";
import { keepPreviousData } from "@tanstack/react-query";
@@ -27,6 +28,7 @@ import { buildDocsUrl, cn } from "@/lib/utils";
import Logo from "@/components/layout/Logo/Logo";
import usePluginsStore from "@/store/PluginsStore";
import ProvideFeedbackDialog from "@/components/layout/SideBar/FeedbackDialog/ProvideFeedbackDialog";
+import usePromptsList from "@/api/prompts/usePromptsList";
enum MENU_ITEM_TYPE {
link = "link",
@@ -53,6 +55,14 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
label: "Projects",
count: "projects",
},
+ {
+ id: "prompts",
+ path: "/$workspaceName/prompts",
+ type: MENU_ITEM_TYPE.router,
+ icon: FileTerminal,
+ label: "Prompts",
+ count: "prompts",
+ },
{
id: "datasets",
path: "/$workspaceName/datasets",
@@ -204,11 +214,24 @@ const SideBar: React.FunctionComponent = ({
},
);
+ const { data: promptsData } = usePromptsList(
+ {
+ workspaceName,
+ page: 1,
+ size: 1,
+ },
+ {
+ placeholderData: keepPreviousData,
+ enabled: expanded,
+ },
+ );
+
const countDataMap: Record = {
projects: projectData?.total,
datasets: datasetsData?.total,
experiments: experimentsData?.total,
feedbackDefinitions: feedbackDefinitions?.total,
+ prompts: promptsData?.total
};
const bottomMenuItems: MenuItem[] = [
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
new file mode 100644
index 000000000..437497c60
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
@@ -0,0 +1,110 @@
+import React, {useCallback, useState} from "react";
+import { Button } from "@/components/ui/button";
+import {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import useAppStore from "@/store/AppStore";
+import { Textarea } from "@/components/ui/textarea";
+import usePromptCreateMutation from "@/api/prompts/usePromptCreateMutation";
+import {Prompt} from "@/types/prompts";
+import {AccordionContent, AccordionItem, AccordionTrigger, Accordion} from "@/components/ui/accordion";
+
+type AddPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+ onPromptCreated?: (prompt: Prompt) => void;
+};
+
+const AddPromptDialog: React.FunctionComponent = ({
+ open,
+ setOpen,
+ onPromptCreated,
+}) => {
+ const workspaceName = useAppStore((state) => state.activeWorkspaceName);
+ const promptCreateMutation = usePromptCreateMutation();
+ const [name, setName] = useState("");
+ const [prompt, setPrompt] = useState("");
+ const [description, setDescription] = useState("");
+
+ const isValid = Boolean(name.length && prompt.length);
+
+ const createPrompt = useCallback(() => {
+ promptCreateMutation.mutate(
+ {
+ prompt: {
+ name,
+ template: prompt,
+ ...(description ? { description } : {}),
+ },
+ workspaceName,
+ },
+ { onSuccess: onPromptCreated },
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [name, description, workspaceName, onPromptCreated]);
+
+ return (
+
+ );
+};
+
+export default AddPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
new file mode 100644
index 000000000..3f77a0793
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
@@ -0,0 +1,67 @@
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Button } from "@/components/ui/button";
+import { MoreHorizontal, Trash } from "lucide-react";
+import React, { useCallback, useRef, useState } from "react";
+import { CellContext } from "@tanstack/react-table";
+import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
+import {Prompt} from "@/types/prompts";
+import usePromptDeleteMutation from "@/api/prompts/usePromptDeleteMutation";
+
+export const PromptRowActionsCell: React.FunctionComponent<
+ CellContext
+> = ({ row }) => {
+ const resetKeyRef = useRef(0);
+ const prompt = row.original;
+ const [open, setOpen] = useState(false);
+
+ const promptDeleteMutation = usePromptDeleteMutation();
+
+ const deletePromptHandler = useCallback(() => {
+ promptDeleteMutation.mutate({
+ promptId: prompt.id,
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [prompt.id]);
+
+ return (
+ e.stopPropagation()}
+ >
+
+
+
+
+ Actions menu
+
+
+
+
+ {
+ setOpen(true);
+ resetKeyRef.current = resetKeyRef.current + 1;
+ }}
+ >
+
+ Delete
+
+
+
+
+
+ );
+};
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
new file mode 100644
index 000000000..ad83388a2
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -0,0 +1,227 @@
+import React, { useCallback, useMemo, useRef, useState } from "react";
+import { useNavigate } from "@tanstack/react-router";
+import { keepPreviousData } from "@tanstack/react-query";
+import DataTable from "@/components/shared/DataTable/DataTable";
+import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
+import DataTableNoData from "@/components/shared/DataTableNoData/DataTableNoData";
+import IdCell from "@/components/shared/DataTableCells/IdCell";
+import Loader from "@/components/shared/Loader/Loader";
+import { Button } from "@/components/ui/button";
+import useAppStore from "@/store/AppStore";
+import SearchInput from "@/components/shared/SearchInput/SearchInput";
+import { formatDate } from "@/lib/date";
+import { COLUMN_TYPE, ColumnData } from "@/types/shared";
+import useLocalStorageState from "use-local-storage-state";
+import { convertColumnDataToColumn } from "@/lib/table";
+import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
+import usePromptsList from "@/api/prompts/usePromptsList";
+import {Prompt} from "@/types/prompts";
+import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
+import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
+import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
+import ResourceCell from "@/components/shared/DataTableCells/ResourceCell";
+import {RESOURCE_TYPE} from "@/components/shared/ResourceLink/ResourceLink";
+
+const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
+const COLUMNS_WIDTH_KEY = "prompts-columns-width";
+const COLUMNS_ORDER_KEY = "prompts-columns-order";
+
+// ALEX
+// ASK ABOUT PUTTING IT INTO A DIFFERENT HOOK FOR COLUMN STATES
+// ADD A key to the sidebar
+
+export const DEFAULT_COLUMNS: ColumnData[] = [
+ {
+ id: "id",
+ label: "ID",
+ type: COLUMN_TYPE.string,
+ cell: IdCell as never,
+ },
+ {
+ id: "name",
+ label: "Name",
+ type: COLUMN_TYPE.string,
+ cell: TagNameCell as never
+ },
+ {
+ id: "versions_count",
+ label: "Versions",
+ type: COLUMN_TYPE.number,
+ },
+ {
+ id: "last_updated_at",
+ label: "Last updated",
+ type: COLUMN_TYPE.time,
+ accessorFn: (row) => formatDate(row.last_updated_at),
+ },
+ {
+ id: "description",
+ label: "Description",
+ type: COLUMN_TYPE.string,
+ },
+];
+
+export const DEFAULT_SELECTED_COLUMNS: string[] = [
+ "name",
+ "versions_count",
+ "last_updated_at",
+ "description",
+];
+
+const PromptsPage: React.FunctionComponent = () => {
+ const navigate = useNavigate();
+ const workspaceName = useAppStore((state) => state.activeWorkspaceName);
+
+ const resetDialogKeyRef = useRef(0);
+ const [openDialog, setOpenDialog] = useState(false);
+ const [search, setSearch] = useState("");
+ const [page, setPage] = useState(1);
+ const [size, setSize] = useState(10);
+ const { data, isPending } = usePromptsList(
+ {
+ workspaceName,
+ search,
+ page,
+ size,
+ },
+ {
+ placeholderData: keepPreviousData,
+ },
+ );
+
+ const prompts = data?.content ?? [];
+ const total = data?.total ?? 0;
+ const noData = !search;
+ const noDataText = noData ? "There are no prompts yet" : "No search results";
+
+ const [selectedColumns, setSelectedColumns] = useLocalStorageState(
+ SELECTED_COLUMNS_KEY,
+ {
+ defaultValue: DEFAULT_SELECTED_COLUMNS,
+ },
+ );
+
+ const [columnsOrder, setColumnsOrder] = useLocalStorageState(
+ COLUMNS_ORDER_KEY,
+ {
+ defaultValue: [],
+ },
+ );
+
+ const [columnsWidth, setColumnsWidth] = useLocalStorageState<
+ Record
+ >(COLUMNS_WIDTH_KEY, {
+ defaultValue: {},
+ });
+
+ const columns = useMemo(() => {
+ const retVal = convertColumnDataToColumn(
+ DEFAULT_COLUMNS,
+ {
+ columnsOrder,
+ columnsWidth,
+ selectedColumns,
+ },
+ );
+
+ retVal.push({
+ id: "actions",
+ enableHiding: false,
+ cell: PromptRowActionsCell,
+ size: 48,
+ enableResizing: false,
+ });
+
+ return retVal;
+ }, [selectedColumns, columnsWidth, columnsOrder]);
+
+ const resizeConfig = useMemo(
+ () => ({
+ enabled: true,
+ onColumnResize: setColumnsWidth,
+ }),
+ [setColumnsWidth],
+ );
+
+ const handleNewDatasetClick = useCallback(() => {
+ setOpenDialog(true);
+ resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
+ }, []);
+
+ const handleRowClick = useCallback(
+ (prompt: Prompt) => {
+ // ALEX
+ // navigate({
+ // to: "/$workspaceName/prompts/$promptId/items",
+ // params: {
+ // promptId: prompt.id,
+ // workspaceName,
+ // },
+ // });
+ },
+ [navigate, workspaceName],
+ );
+
+ if (isPending) {
+ return ;
+ }
+
+ return (
+
+
+
Prompts
+
+
+
+
+
+
+ Create new prompt
+
+
+
+
+ {noData && (
+
+ Create new prompt
+
+ )}
+
+ }
+ />
+
+
+
+
+
+ );
+};
+
+export default PromptsPage;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
new file mode 100644
index 000000000..70285fc37
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+import { CellContext } from "@tanstack/react-table";
+import { Tag } from "@/components/ui/tag";
+import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
+import {ArrowUpRight} from "lucide-react";
+import {Prompt} from "@/types/prompts";
+
+
+const TagNameCell = (context: CellContext) => {
+ const value = context.getValue();
+
+ return (
+
+
+ {value}
+
+
+
+ );
+};
+
+export default TagNameCell;
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index 0ad731447..b5deff74c 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -22,6 +22,7 @@ import ProjectPage from "@/components/pages/ProjectPage/ProjectPage";
import ProjectsPage from "@/components/pages/ProjectsPage/ProjectsPage";
import TracesPage from "@/components/pages/TracesPage/TracesPage";
import WorkspacePage from "@/components/pages/WorkspacePage/WorkspacePage";
+import PromptsPage from "@/components/pages/PromptsPage/PromptsPage";
const TanStackRouterDevtools =
process.env.NODE_ENV === "production"
@@ -184,6 +185,21 @@ const datasetItemsRoute = createRoute({
},
});
+// ----------- prompts
+const promptsRoute = createRoute({
+ path: "/prompts",
+ getParentRoute: () => workspaceRoute,
+ staticData: {
+ title: "Prompts",
+ },
+});
+
+const promptsListRoute = createRoute({
+ path: "/",
+ getParentRoute: () => promptsRoute,
+ component: PromptsPage,
+});
+
const routeTree = rootRoute.addChildren([
workspaceGuardPartialLayoutRoute.addChildren([
getStartedRoute,
@@ -205,6 +221,9 @@ const routeTree = rootRoute.addChildren([
datasetsListRoute,
datasetRoute.addChildren([datasetItemsRoute]),
]),
+ promptsRoute.addChildren([
+ promptsListRoute,
+ ])
]),
]),
]);
diff --git a/apps/opik-frontend/src/types/prompts.ts b/apps/opik-frontend/src/types/prompts.ts
new file mode 100644
index 000000000..ee174ddbd
--- /dev/null
+++ b/apps/opik-frontend/src/types/prompts.ts
@@ -0,0 +1,8 @@
+export interface Prompt {
+ id: string;
+ name: string;
+ description: string;
+ last_updated_at: string;
+ created_at: string;
+ versions_count: number;
+}
From 4ca0b89e1e23a7194a22aaffbc3a8eefc569f081 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:47:05 +0100
Subject: [PATCH 14/45] [OPIK-347]: removed unused vars;
---
apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts | 2 +-
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
index dc01359e9..ca57ddf28 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -24,7 +24,7 @@ const usePromptCreateMutation = () => {
prompt,
workspaceName,
}: UsePromptCreateMutationParams) => {
- const { data, headers } = await api.post(PROMPTS_REST_ENDPOINT, {
+ const { data } = await api.post(PROMPTS_REST_ENDPOINT, {
...prompt,
workspace_name: workspaceName,
});
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index ad83388a2..87dca605c 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -19,8 +19,6 @@ import {Prompt} from "@/types/prompts";
import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
-import ResourceCell from "@/components/shared/DataTableCells/ResourceCell";
-import {RESOURCE_TYPE} from "@/components/shared/ResourceLink/ResourceLink";
const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
const COLUMNS_WIDTH_KEY = "prompts-columns-width";
From fddbf7eb50d421835dc93ff0c4972acf5ef8434b Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:50:24 +0100
Subject: [PATCH 15/45] [OPIK-347]: update the prompt page name;
---
apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx | 2 +-
apps/opik-frontend/src/router.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index a45bcf1db..8848a15c5 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -60,7 +60,7 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
path: "/$workspaceName/prompts",
type: MENU_ITEM_TYPE.router,
icon: FileTerminal,
- label: "Prompts",
+ label: "Prompts library",
count: "prompts",
},
{
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index b5deff74c..93e83ba52 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -190,7 +190,7 @@ const promptsRoute = createRoute({
path: "/prompts",
getParentRoute: () => workspaceRoute,
staticData: {
- title: "Prompts",
+ title: "Prompts library",
},
});
From c37a7b6a7ddb14adf1a0c6676c89974240eef90a Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 11:51:47 +0100
Subject: [PATCH 16/45] [OPIK-347]: update the prompt page name;
---
apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx | 2 +-
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 +-
apps/opik-frontend/src/router.tsx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 8848a15c5..5bedbd1ec 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -60,7 +60,7 @@ const MAIN_MENU_ITEMS: MenuItem[] = [
path: "/$workspaceName/prompts",
type: MENU_ITEM_TYPE.router,
icon: FileTerminal,
- label: "Prompts library",
+ label: "Prompt library",
count: "prompts",
},
{
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 87dca605c..ff700ce97 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -167,7 +167,7 @@ const PromptsPage: React.FunctionComponent = () => {
return (
-
Prompts
+ Prompt library
workspaceRoute,
staticData: {
- title: "Prompts library",
+ title: "Prompt library",
},
});
From eb3c866bc896ff615896f9ed0c562e666b939594 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:02:03 +0100
Subject: [PATCH 17/45] [OPIK-347]: eslint error fixes;
---
apps/opik-frontend/src/api/api.ts | 1 -
.../api/prompts/usePromptCreateMutation.ts | 4 +-
.../api/prompts/usePromptDeleteMutation.ts | 2 +-
.../src/api/prompts/usePromptsList.ts | 165 +++++++++---------
.../src/components/layout/SideBar/SideBar.tsx | 4 +-
.../pages/PromptsPage/AddPromptDialog.tsx | 18 +-
.../PromptsPage/PromptRowActionsCell.tsx | 3 +-
.../pages/PromptsPage/PromptsPage.tsx | 42 ++---
.../pages/PromptsPage/TagNameCell.tsx | 5 +-
apps/opik-frontend/src/router.tsx | 4 +-
10 files changed, 122 insertions(+), 126 deletions(-)
diff --git a/apps/opik-frontend/src/api/api.ts b/apps/opik-frontend/src/api/api.ts
index 34e94eb11..486d296aa 100644
--- a/apps/opik-frontend/src/api/api.ts
+++ b/apps/opik-frontend/src/api/api.ts
@@ -17,7 +17,6 @@ export const TRACES_REST_ENDPOINT = "/v1/private/traces/";
export const SPANS_REST_ENDPOINT = "/v1/private/spans/";
export const PROMPTS_REST_ENDPOINT = "/v1/private/prompts/";
-
export type QueryConfig = Omit<
UseQueryOptions<
TQueryFnData,
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
index ca57ddf28..4ed9e2d63 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -2,9 +2,9 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import get from "lodash/get";
-import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
import { useToast } from "@/components/ui/use-toast";
-import {Prompt} from "@/types/prompts";
+import { Prompt } from "@/types/prompts";
interface CreatePromptTemplate {
template: string;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
index 509a31008..b60bc6428 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptDeleteMutation.ts
@@ -1,7 +1,7 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import get from "lodash/get";
import { useToast } from "@/components/ui/use-toast";
-import api, {PROMPTS_REST_ENDPOINT} from "@/api/api";
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
type UsePromptDeleteMutationParams = {
promptId: string;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 9007f2769..45c8f9a22 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -1,6 +1,6 @@
import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
-import api, {PROMPTS_REST_ENDPOINT, QueryConfig} from "@/api/api";
-import {Prompt} from "@/types/prompts";
+import { QueryConfig } from "@/api/api";
+import { Prompt } from "@/types/prompts";
type UsePromptsListParams = {
workspaceName: string;
@@ -17,107 +17,106 @@ type UsePromptsListResponse = {
// ALEX
const FAKE_PROMPTS: Prompt[] = [
{
- "id": "4338ec03-6ee9-4635-b071-77849626b948",
- "name": "Item 1123421342134341234812349123841239048132094812304123804301294",
- "description": "This is a description for Item 1.",
- "last_updated_at": "2022-04-15 00:00:00",
- "created_at": "2020-09-09 00:00:00",
- "versions_count": 6
+ id: "4338ec03-6ee9-4635-b071-77849626b948",
+ name: "Item 1123421342134341234812349123841239048132094812304123804301294",
+ description: "This is a description for Item 1.",
+ last_updated_at: "2022-04-15 00:00:00",
+ created_at: "2020-09-09 00:00:00",
+ versions_count: 6,
},
{
- "id": "2ac76571-520f-4664-9ad5-1439492ad557",
- "name": "Item 2",
- "description": "This is a description for Item 2.",
- "last_updated_at": "2022-08-19 00:00:00",
- "created_at": "2021-10-27 00:00:00",
- "versions_count": 4
+ id: "2ac76571-520f-4664-9ad5-1439492ad557",
+ name: "Item 2",
+ description: "This is a description for Item 2.",
+ last_updated_at: "2022-08-19 00:00:00",
+ created_at: "2021-10-27 00:00:00",
+ versions_count: 4,
},
{
- "id": "3ba74f16-698f-4318-9427-d26403bc117b",
- "name": "Item 3",
- "description": "This is a description for Item 3.",
- "last_updated_at": "2023-12-12 00:00:00",
- "created_at": "2021-10-08 00:00:00",
- "versions_count": 5
+ id: "3ba74f16-698f-4318-9427-d26403bc117b",
+ name: "Item 3",
+ description: "This is a description for Item 3.",
+ last_updated_at: "2023-12-12 00:00:00",
+ created_at: "2021-10-08 00:00:00",
+ versions_count: 5,
},
{
- "id": "bbef9b6c-d991-4132-9c08-24e1584ccea2",
- "name": "Item 4",
- "description": "This is a description for Item 4.",
- "last_updated_at": "2023-05-14 00:00:00",
- "created_at": "2023-01-04 00:00:00",
- "versions_count": 10
+ id: "bbef9b6c-d991-4132-9c08-24e1584ccea2",
+ name: "Item 4",
+ description: "This is a description for Item 4.",
+ last_updated_at: "2023-05-14 00:00:00",
+ created_at: "2023-01-04 00:00:00",
+ versions_count: 10,
},
{
- "id": "57c82e2b-3d75-4f16-87ac-3201554ea84d",
- "name": "Item 5",
- "description": "This is a description for Item 5.",
- "last_updated_at": "2022-06-10 00:00:00",
- "created_at": "2021-10-06 00:00:00",
- "versions_count": 4
+ id: "57c82e2b-3d75-4f16-87ac-3201554ea84d",
+ name: "Item 5",
+ description: "This is a description for Item 5.",
+ last_updated_at: "2022-06-10 00:00:00",
+ created_at: "2021-10-06 00:00:00",
+ versions_count: 4,
},
{
- "id": "caad2d07-6be4-4e30-8e54-45928c4c675c",
- "name": "Item 6",
- "description": "This is a description for Item 6.",
- "last_updated_at": "2023-11-07 00:00:00",
- "created_at": "2022-04-26 00:00:00",
- "versions_count": 7
+ id: "caad2d07-6be4-4e30-8e54-45928c4c675c",
+ name: "Item 6",
+ description: "This is a description for Item 6.",
+ last_updated_at: "2023-11-07 00:00:00",
+ created_at: "2022-04-26 00:00:00",
+ versions_count: 7,
},
{
- "id": "955439b8-2199-4edb-bfff-0becef27f477",
- "name": "Item 7",
- "description": "This is a description for Item 7.",
- "last_updated_at": "2023-09-21 00:00:00",
- "created_at": "2023-08-15 00:00:00",
- "versions_count": 5
+ id: "955439b8-2199-4edb-bfff-0becef27f477",
+ name: "Item 7",
+ description: "This is a description for Item 7.",
+ last_updated_at: "2023-09-21 00:00:00",
+ created_at: "2023-08-15 00:00:00",
+ versions_count: 5,
},
{
- "id": "059452b9-9050-4b99-893f-8e809adae877",
- "name": "Item 8",
- "description": "This is a description for Item 8.",
- "last_updated_at": "2023-04-10 00:00:00",
- "created_at": "2022-09-22 00:00:00",
- "versions_count": 8
+ id: "059452b9-9050-4b99-893f-8e809adae877",
+ name: "Item 8",
+ description: "This is a description for Item 8.",
+ last_updated_at: "2023-04-10 00:00:00",
+ created_at: "2022-09-22 00:00:00",
+ versions_count: 8,
},
{
- "id": "c46f907a-7e35-4d35-a482-fb4a7fee3967",
- "name": "Item 9",
- "description": "This is a description for Item 9.",
- "last_updated_at": "2023-12-22 00:00:00",
- "created_at": "2023-05-13 00:00:00",
- "versions_count": 8
+ id: "c46f907a-7e35-4d35-a482-fb4a7fee3967",
+ name: "Item 9",
+ description: "This is a description for Item 9.",
+ last_updated_at: "2023-12-22 00:00:00",
+ created_at: "2023-05-13 00:00:00",
+ versions_count: 8,
},
{
- "id": "c4365771-f654-4434-9272-8e22f623906b",
- "name": "Item 10",
- "description": "This is a description for Item 10.",
- "last_updated_at": "2023-09-09 00:00:00",
- "created_at": "2022-12-02 00:00:00",
- "versions_count": 6
- }
-]
-
+ id: "c4365771-f654-4434-9272-8e22f623906b",
+ name: "Item 10",
+ description: "This is a description for Item 10.",
+ last_updated_at: "2023-09-09 00:00:00",
+ created_at: "2022-12-02 00:00:00",
+ versions_count: 6,
+ },
+];
-const getPromptsList = async (
- { signal }: QueryFunctionContext,
- { workspaceName, search, size, page }: UsePromptsListParams,
-) => {
- // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
- // signal,
- // params: {
- // workspace_name: workspaceName,
- // ...(search && { name: search }),
- // size,
- // page,
- // },
- // });
+const getPromptsList = async () =>
+ // { signal }: QueryFunctionContext,
+ // { workspaceName, search, size, page }: UsePromptsListParams,
+ {
+ // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
+ // signal,
+ // params: {
+ // workspace_name: workspaceName,
+ // ...(search && { name: search }),
+ // size,
+ // page,
+ // },
+ // });
- return {
- content: FAKE_PROMPTS,
- total: FAKE_PROMPTS.length,
+ return {
+ content: FAKE_PROMPTS,
+ total: FAKE_PROMPTS.length,
+ };
};
-};
export default function usePromptsList(
params: UsePromptsListParams,
@@ -125,7 +124,7 @@ export default function usePromptsList(
) {
return useQuery({
queryKey: ["prompts", params],
- queryFn: (context) => getPromptsList(context, params),
+ queryFn: (context) => getPromptsList(),
...options,
});
}
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 5bedbd1ec..1bd7b916f 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -11,7 +11,7 @@ import {
MessageSquare,
PanelLeftClose,
MessageCircleQuestion,
- FileTerminal
+ FileTerminal,
} from "lucide-react";
import { keepPreviousData } from "@tanstack/react-query";
@@ -231,7 +231,7 @@ const SideBar: React.FunctionComponent = ({
datasets: datasetsData?.total,
experiments: experimentsData?.total,
feedbackDefinitions: feedbackDefinitions?.total,
- prompts: promptsData?.total
+ prompts: promptsData?.total,
};
const bottomMenuItems: MenuItem[] = [
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
index 437497c60..671b8f8d0 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useState} from "react";
+import React, { useCallback, useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -13,8 +13,13 @@ import { Label } from "@/components/ui/label";
import useAppStore from "@/store/AppStore";
import { Textarea } from "@/components/ui/textarea";
import usePromptCreateMutation from "@/api/prompts/usePromptCreateMutation";
-import {Prompt} from "@/types/prompts";
-import {AccordionContent, AccordionItem, AccordionTrigger, Accordion} from "@/components/ui/accordion";
+import { Prompt } from "@/types/prompts";
+import {
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+ Accordion,
+} from "@/components/ui/accordion";
type AddPromptDialogProps = {
open: boolean;
@@ -74,9 +79,12 @@ const AddPromptDialog: React.FunctionComponent = ({
value={prompt}
onChange={(event) => setPrompt(event.target.value)}
/>
- You can specify variables using the "mustache" syntax: {"{{variable}}"}.
+
+ You can specify variables using the "mustache" syntax:{" "}
+ {"{{variable}}"}.
+
-
+
Description
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
index 3f77a0793..ac77ad530 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
@@ -9,7 +9,7 @@ import { MoreHorizontal, Trash } from "lucide-react";
import React, { useCallback, useRef, useState } from "react";
import { CellContext } from "@tanstack/react-table";
import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
-import {Prompt} from "@/types/prompts";
+import { Prompt } from "@/types/prompts";
import usePromptDeleteMutation from "@/api/prompts/usePromptDeleteMutation";
export const PromptRowActionsCell: React.FunctionComponent<
@@ -59,7 +59,6 @@ export const PromptRowActionsCell: React.FunctionComponent<
Delete
-
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index ff700ce97..550dedd9a 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -15,8 +15,8 @@ import useLocalStorageState from "use-local-storage-state";
import { convertColumnDataToColumn } from "@/lib/table";
import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
import usePromptsList from "@/api/prompts/usePromptsList";
-import {Prompt} from "@/types/prompts";
-import {PromptRowActionsCell} from "@/components/pages/PromptsPage/PromptRowActionsCell";
+import { Prompt } from "@/types/prompts";
+import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
@@ -39,7 +39,7 @@ export const DEFAULT_COLUMNS: ColumnData
[] = [
id: "name",
label: "Name",
type: COLUMN_TYPE.string,
- cell: TagNameCell as never
+ cell: TagNameCell as never,
},
{
id: "versions_count",
@@ -113,14 +113,11 @@ const PromptsPage: React.FunctionComponent = () => {
});
const columns = useMemo(() => {
- const retVal = convertColumnDataToColumn(
- DEFAULT_COLUMNS,
- {
- columnsOrder,
- columnsWidth,
- selectedColumns,
- },
- );
+ const retVal = convertColumnDataToColumn(DEFAULT_COLUMNS, {
+ columnsOrder,
+ columnsWidth,
+ selectedColumns,
+ });
retVal.push({
id: "actions",
@@ -146,19 +143,16 @@ const PromptsPage: React.FunctionComponent = () => {
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
- const handleRowClick = useCallback(
- (prompt: Prompt) => {
- // ALEX
- // navigate({
- // to: "/$workspaceName/prompts/$promptId/items",
- // params: {
- // promptId: prompt.id,
- // workspaceName,
- // },
- // });
- },
- [navigate, workspaceName],
- );
+ const handleRowClick = useCallback(() => {
+ // ALEX
+ // navigate({
+ // to: "/$workspaceName/prompts/$promptId/items",
+ // params: {
+ // promptId: prompt.id,
+ // workspaceName,
+ // },
+ // });
+ }, [navigate, workspaceName]);
if (isPending) {
return ;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
index 70285fc37..066421fde 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
@@ -2,9 +2,8 @@ import React from "react";
import { CellContext } from "@tanstack/react-table";
import { Tag } from "@/components/ui/tag";
import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
-import {ArrowUpRight} from "lucide-react";
-import {Prompt} from "@/types/prompts";
-
+import { ArrowUpRight } from "lucide-react";
+import { Prompt } from "@/types/prompts";
const TagNameCell = (context: CellContext) => {
const value = context.getValue();
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index 498e2ae27..607ba067e 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -221,9 +221,7 @@ const routeTree = rootRoute.addChildren([
datasetsListRoute,
datasetRoute.addChildren([datasetItemsRoute]),
]),
- promptsRoute.addChildren([
- promptsListRoute,
- ])
+ promptsRoute.addChildren([promptsListRoute]),
]),
]),
]);
From f78a1bcbfe71236ca04e9683a40b860782ec7053 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:02:26 +0100
Subject: [PATCH 18/45] [OPIK-347]: eslint error fixes;
---
apps/opik-frontend/src/api/prompts/usePromptsList.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 45c8f9a22..1cac9fdde 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -1,4 +1,4 @@
-import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import { useQuery } from "@tanstack/react-query";
import { QueryConfig } from "@/api/api";
import { Prompt } from "@/types/prompts";
@@ -124,7 +124,7 @@ export default function usePromptsList(
) {
return useQuery({
queryKey: ["prompts", params],
- queryFn: (context) => getPromptsList(),
+ queryFn: () => getPromptsList(),
...options,
});
}
From b1d3f8169e4a3d65c38a1c1bc2e4bb19a876d25a Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:04:31 +0100
Subject: [PATCH 19/45] [OPIK-347]: remove not needed dependencies from the
usecallback;
---
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 550dedd9a..68ff60d30 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -152,7 +152,7 @@ const PromptsPage: React.FunctionComponent = () => {
// workspaceName,
// },
// });
- }, [navigate, workspaceName]);
+ }, []);
if (isPending) {
return ;
From e11300c726112b17265dfbe5aa4a31499a150ed6 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Mon, 4 Nov 2024 12:06:21 +0100
Subject: [PATCH 20/45] [OPIK-347]: remove navigate;
---
.../src/components/pages/PromptsPage/PromptsPage.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 68ff60d30..fc23f9753 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -1,5 +1,4 @@
import React, { useCallback, useMemo, useRef, useState } from "react";
-import { useNavigate } from "@tanstack/react-router";
import { keepPreviousData } from "@tanstack/react-query";
import DataTable from "@/components/shared/DataTable/DataTable";
import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
@@ -67,7 +66,6 @@ export const DEFAULT_SELECTED_COLUMNS: string[] = [
];
const PromptsPage: React.FunctionComponent = () => {
- const navigate = useNavigate();
const workspaceName = useAppStore((state) => state.activeWorkspaceName);
const resetDialogKeyRef = useRef(0);
From affdc8fc1e0c248266b746e8a47150599185a165 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Tue, 5 Nov 2024 14:45:18 +0100
Subject: [PATCH 21/45] [OPIK-349]: add a prompt tab;
---
.../prompts/useCreatePromptVersionMutation.ts | 49 ++++++++++
.../src/api/prompts/usePromptById.ts | 52 +++++++++++
.../src/api/prompts/usePromptsVersionsById.ts | 93 +++++++++++++++++++
.../CompareExperimentsDetails.tsx | 12 +--
.../pages/PromptPage/PromptPage.tsx | 70 ++++++++++++++
.../PromptPage/PromptTab/CommitHistory.tsx | 62 +++++++++++++
.../PromptPage/PromptTab/EditPromptDialog.tsx | 75 +++++++++++++++
.../pages/PromptPage/PromptTab/PromptTab.tsx | 90 ++++++++++++++++++
.../PromptTab/UseThisPromptDialog.tsx | 31 +++++++
.../pages/PromptsPage/PromptsPage.tsx | 20 ++--
.../src/components/shared/DateTag/DateTag.tsx | 21 +++++
.../TraceAnnotateViewer/AnnotateRow.tsx | 6 +-
.../src/components/ui/button.tsx | 1 +
.../src/hooks/usePromptIdFromURL.ts | 8 ++
apps/opik-frontend/src/router.tsx | 12 ++-
apps/opik-frontend/src/types/prompts.ts | 17 ++++
16 files changed, 594 insertions(+), 25 deletions(-)
create mode 100644 apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptById.ts
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
create mode 100644 apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
create mode 100644 apps/opik-frontend/src/hooks/usePromptIdFromURL.ts
diff --git a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
new file mode 100644
index 000000000..a93333f04
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
@@ -0,0 +1,49 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { AxiosError } from "axios";
+import get from "lodash/get";
+
+import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
+import { useToast } from "@/components/ui/use-toast";
+
+type UseCreatePromptVersionMutationParams = {
+ name: string;
+ id: string;
+ template: string;
+};
+
+const useCreatePromptVersionMutation = () => {
+ const queryClient = useQueryClient();
+ const { toast } = useToast();
+
+ return useMutation({
+ mutationFn: async ({
+ name,
+ id,
+ template,
+ }: UseCreatePromptVersionMutationParams) => {
+ const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}/versions`, {
+ ...prompt,
+ });
+
+ return data;
+ },
+ onError: (error: AxiosError) => {
+ const message = get(
+ error,
+ ["response", "data", "message"],
+ error.message,
+ );
+
+ toast({
+ title: "Error",
+ description: message,
+ variant: "destructive",
+ });
+ },
+ onSettled: (data, error, variables, context) => {
+ return queryClient.invalidateQueries({ queryKey: ["prompt-versions"] });
+ },
+ });
+};
+
+export default useCreatePromptVersionMutation;
diff --git a/apps/opik-frontend/src/api/prompts/usePromptById.ts b/apps/opik-frontend/src/api/prompts/usePromptById.ts
new file mode 100644
index 000000000..818a86aa9
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptById.ts
@@ -0,0 +1,52 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
+import { PromptWithLatestVersion } from "@/types/prompts";
+
+// ALEX
+const FAKE_PROMPT = {
+ id: "p001",
+ name: "Product Recommendation Prompt",
+ description:
+ "A prompt designed to generate product recommendations based on user preferences.",
+ last_updated_at: "2024-11-04T14:35:00Z",
+ created_at: "2024-10-20T09:00:00Z",
+ versions_count: 3,
+
+ latest_version: {
+ id: "v003",
+ created_at: "2024-11-04T14:35:00Z",
+ template:
+ "Recommend products to {{username}} based on preferences in {{category}} and previous interactions.",
+ variables: ["username", "category"],
+ },
+};
+
+const getPromptById = async (
+ { signal }: QueryFunctionContext,
+ { promptId }: UsePromptByIdParams,
+) => {
+ try {
+ const { data } = await api.get(`${PROMPTS_REST_ENDPOINT}/${promptId}`, {
+ signal,
+ });
+
+ return data;
+ } catch {
+ return FAKE_PROMPT;
+ }
+};
+
+type UsePromptByIdParams = {
+ promptId: string;
+};
+
+export default function usePromptById(
+ params: UsePromptByIdParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompt", params],
+ queryFn: (context) => getPromptById(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts b/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
new file mode 100644
index 000000000..99ccdbec4
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
@@ -0,0 +1,93 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
+import { CompactPromptVersion } from "@/types/prompts";
+
+// ALEX
+const FAKE_PROMPT_VERSIONS: CompactPromptVersion[] = [
+ {
+ id: "prompt_1234123412341234123412341241231",
+ created_at: "2023-10-01T08:30:00Z",
+ },
+ {
+ id: "prompt_2",
+ created_at: "2023-10-02T10:15:00Z",
+ },
+ {
+ id: "prompt_3",
+ created_at: "2023-10-03T12:45:00Z",
+ },
+ {
+ id: "prompt_4",
+ created_at: "2023-10-04T15:20:00Z",
+ },
+ {
+ id: "prompt_5",
+ created_at: "2023-10-05T18:05:00Z",
+ },
+ {
+ id: "prompt_6",
+ created_at: "2023-10-06T09:40:00Z",
+ },
+ {
+ id: "prompt_7",
+ created_at: "2023-10-07T11:25:00Z",
+ },
+ {
+ id: "prompt_8",
+ created_at: "2023-10-08T13:55:00Z",
+ },
+ {
+ id: "prompt_9",
+ created_at: "2023-10-09T16:10:00Z",
+ },
+ {
+ id: "prompt_10",
+ created_at: "2023-10-10T19:30:00Z",
+ },
+];
+
+const getPromptVersionsById = async (
+ { signal }: QueryFunctionContext,
+ { promptId, size, page, search }: UsePromptVersionsByIdParams,
+) => {
+ try {
+ const { data } = await api.get(
+ `${PROMPTS_REST_ENDPOINT}/${promptId}/versions`,
+ {
+ signal,
+ params: {
+ ...(search && { name: search }),
+ size,
+ page,
+ },
+ },
+ );
+
+ return data;
+ } catch {
+ return { content: FAKE_PROMPT_VERSIONS };
+ }
+};
+
+type UsePromptVersionsByIdParams = {
+ promptId: string;
+ search?: string;
+ page: number;
+ size: number;
+};
+
+type UsePromptsVersionsByIdResponse = {
+ content: CompactPromptVersion[];
+ total: number;
+};
+
+export default function usePromptVersionsById(
+ params: UsePromptVersionsByIdParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompt-versions", params],
+ queryFn: (context) => getPromptVersionsById(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
index 2d3f87aad..693766cc4 100644
--- a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
+++ b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
@@ -21,6 +21,7 @@ import { Button } from "@/components/ui/button";
import ResourceLink, {
RESOURCE_TYPE,
} from "@/components/shared/ResourceLink/ResourceLink";
+import DateTag from "@/components/shared/DateTag/DateTag";
type CompareExperimentsDetailsProps = {
experimentsIds: string[];
@@ -201,16 +202,7 @@ const CompareExperimentsDetails: React.FunctionComponent<
{renderCompareFeedbackScoresButton()}
- {!isCompare && (
-
-
- {formatDate(experiment?.created_at)}
-
- )}
+ {!isCompare &&
}
{
+ const [tab, setTab] = useQueryParam("tab", StringParam, {
+ updateType: "replaceIn",
+ });
+
+ const promptId = usePromptIdFromURL();
+
+ const { data: prompt } = usePromptById({ promptId }, { enabled: !!promptId });
+ const promptName = prompt?.name || "";
+ const setBreadcrumbParam = useBreadcrumbsStore((state) => state.setParam);
+
+ useEffect(() => {
+ if (promptId && promptName) {
+ setBreadcrumbParam("promptId", promptId, promptName);
+ }
+ }, [promptId, promptName]);
+
+ useEffect(() => {
+ if (!tab) {
+ setTab("prompt");
+ }
+ }, [tab]);
+
+ return (
+
+
+
+
{promptName}
+
+
+ {prompt?.created_at && (
+
+
+
+ )}
+
+
+
+
+
+ Prompt
+
+
+ Experiments
+
+
+ Commits
+
+
+
+
+
+ Experiments
+ Commits
+
+
+ );
+};
+
+export default PromptPage;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
new file mode 100644
index 000000000..b3ff6dfc5
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -0,0 +1,62 @@
+import { Copy, GitCommitVertical } from "lucide-react";
+import copy from "clipboard-copy";
+
+import { formatDate } from "@/lib/date";
+import React, { useState } from "react";
+import { CompactPromptVersion } from "@/types/prompts";
+import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
+import { Button } from "@/components/ui/button";
+import { useToast } from "@/components/ui/use-toast";
+
+interface CommitHistoryProps {
+ versions: CompactPromptVersion[];
+}
+
+const CommitHistory = ({ versions }: CommitHistoryProps) => {
+ const { toast } = useToast();
+ const [hoveredVersionId, setHoveredVersionId] = useState(null);
+
+ const handleCopyClick = async (versionId: string) => {
+ await copy(versionId);
+
+ toast({
+ description: "ID successfully copied to clipboard",
+ });
+ };
+
+ return (
+
+ );
+};
+
+export default CommitHistory;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
new file mode 100644
index 000000000..1624d29c1
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -0,0 +1,75 @@
+import React, { useState } from "react";
+
+import {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Textarea } from "@/components/ui/textarea";
+import { Label } from "@/components/ui/label";
+import { Button } from "@/components/ui/button";
+
+type EditPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+
+ promptTemplate: string;
+ promptId: string;
+};
+
+const EditPromptDialog: React.FunctionComponent = ({
+ open,
+ setOpen,
+ promptTemplate: parentPromptTemplate,
+}) => {
+ const [promptTemplate, setPromptTemplate] = useState(parentPromptTemplate);
+
+ const isValid =
+ promptTemplate?.length && promptTemplate !== parentPromptTemplate;
+
+ return (
+
+ );
+};
+
+export default EditPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
new file mode 100644
index 000000000..293b49ce2
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -0,0 +1,90 @@
+import React, { useMemo, useRef, useState } from "react";
+
+import { Button } from "@/components/ui/button";
+import { Info, Pencil } from "lucide-react";
+import { PromptWithLatestVersion } from "@/types/prompts";
+import Loader from "@/components/shared/Loader/Loader";
+import usePromptVersionsById from "@/api/prompts/usePromptsVersionsById";
+import UseThisPromptDialog from "@/components/pages/PromptPage/PromptTab/UseThisPromptDialog";
+import EditPromptDialog from "@/components/pages/PromptPage/PromptTab/EditPromptDialog";
+import CommitHistory from "@/components/pages/PromptPage/PromptTab/CommitHistory";
+
+interface PromptTabInterface {
+ prompt?: PromptWithLatestVersion;
+}
+
+const PromptTab = ({ prompt }: PromptTabInterface) => {
+ const [openUseThisPrompt, setOpenUseThisPrompt] = useState(false);
+ const [openEditPrompt, setOpenEditPrompt] = useState(false);
+ const editPromptResetKeyRef = useRef(0);
+ const { data } = usePromptVersionsById(
+ {
+ promptId: prompt?.id || "",
+ page: 1,
+ size: 25,
+ },
+ {
+ enabled: !!prompt?.id,
+ },
+ );
+
+ const versions = data?.content;
+
+ const handleOpenEditPrompt = (value: boolean) => {
+ editPromptResetKeyRef.current += 1;
+ setOpenEditPrompt(value);
+ };
+
+ if (!prompt) {
+ return ;
+ }
+
+ return (
+ <>
+
+
+
setOpenUseThisPrompt(true)}>
+
+ Use this prompt
+
+
+
setOpenEditPrompt(true)}>
+
+ Edit prompt
+
+
+
+
+
+
Prompt
+
+ {prompt?.latest_version?.template}
+
+
+
+
+ Commit history
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default PromptTab;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
new file mode 100644
index 000000000..cb0f97866
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/UseThisPromptDialog.tsx
@@ -0,0 +1,31 @@
+import React from "react";
+
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+
+type UseThisPromptDialogProps = {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+};
+
+const UseThisPromptDialog: React.FunctionComponent<
+ UseThisPromptDialogProps
+> = ({ open, setOpen }) => {
+ return (
+
+ );
+};
+
+export default UseThisPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index fc23f9753..64c7654d7 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -18,6 +18,7 @@ import { Prompt } from "@/types/prompts";
import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
+import { useNavigate } from "@tanstack/react-router";
const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
const COLUMNS_WIDTH_KEY = "prompts-columns-width";
@@ -66,6 +67,8 @@ export const DEFAULT_SELECTED_COLUMNS: string[] = [
];
const PromptsPage: React.FunctionComponent = () => {
+ const navigate = useNavigate();
+
const workspaceName = useAppStore((state) => state.activeWorkspaceName);
const resetDialogKeyRef = useRef(0);
@@ -141,15 +144,14 @@ const PromptsPage: React.FunctionComponent = () => {
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
- const handleRowClick = useCallback(() => {
- // ALEX
- // navigate({
- // to: "/$workspaceName/prompts/$promptId/items",
- // params: {
- // promptId: prompt.id,
- // workspaceName,
- // },
- // });
+ const handleRowClick = useCallback((prompt: Prompt) => {
+ navigate({
+ to: "/$workspaceName/prompts/$promptId",
+ params: {
+ promptId: prompt.id,
+ workspaceName,
+ },
+ });
}, []);
if (isPending) {
diff --git a/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx b/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
new file mode 100644
index 000000000..17f39b202
--- /dev/null
+++ b/apps/opik-frontend/src/components/shared/DateTag/DateTag.tsx
@@ -0,0 +1,21 @@
+import { Clock } from "lucide-react";
+import { formatDate } from "@/lib/date";
+import { Tag } from "@/components/ui/tag";
+import React from "react";
+
+interface DateTagProps {
+ date: string;
+}
+
+const DateTag = ({ date }: DateTagProps) => {
+ return (
+
+
+ {formatDate(date)}
+
+ );
+};
+
+DateTag.displayName = "DateTag";
+
+export default DateTag;
diff --git a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
index 13ba41608..195c78b0a 100644
--- a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
+++ b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
@@ -167,11 +167,7 @@ const AnnotateRow: React.FunctionComponent = ({
{!isUndefined(feedbackScore?.value) && (
-
+
)}
diff --git a/apps/opik-frontend/src/components/ui/button.tsx b/apps/opik-frontend/src/components/ui/button.tsx
index 1473505e3..6fd1852f3 100644
--- a/apps/opik-frontend/src/components/ui/button.tsx
+++ b/apps/opik-frontend/src/components/ui/button.tsx
@@ -33,6 +33,7 @@ const buttonVariants = cva(
"icon-sm": "size-8",
"icon-lg": "size-11",
"icon-xs": "size-6",
+ "icon-xxs": "size-4",
},
},
defaultVariants: {
diff --git a/apps/opik-frontend/src/hooks/usePromptIdFromURL.ts b/apps/opik-frontend/src/hooks/usePromptIdFromURL.ts
new file mode 100644
index 000000000..4a58554aa
--- /dev/null
+++ b/apps/opik-frontend/src/hooks/usePromptIdFromURL.ts
@@ -0,0 +1,8 @@
+import { useParams } from "@tanstack/react-router";
+
+export const usePromptIdFromURL = () => {
+ return useParams({
+ select: (params) => params["promptId"],
+ from: "/workspaceGuard/$workspaceName/prompts/$promptId",
+ });
+};
diff --git a/apps/opik-frontend/src/router.tsx b/apps/opik-frontend/src/router.tsx
index 607ba067e..6c14571fe 100644
--- a/apps/opik-frontend/src/router.tsx
+++ b/apps/opik-frontend/src/router.tsx
@@ -23,6 +23,7 @@ import ProjectsPage from "@/components/pages/ProjectsPage/ProjectsPage";
import TracesPage from "@/components/pages/TracesPage/TracesPage";
import WorkspacePage from "@/components/pages/WorkspacePage/WorkspacePage";
import PromptsPage from "@/components/pages/PromptsPage/PromptsPage";
+import PromptPage from "@/components/pages/PromptPage/PromptPage";
const TanStackRouterDevtools =
process.env.NODE_ENV === "production"
@@ -200,6 +201,15 @@ const promptsListRoute = createRoute({
component: PromptsPage,
});
+const promptRoute = createRoute({
+ path: "/$promptId",
+ getParentRoute: () => promptsRoute,
+ component: PromptPage,
+ staticData: {
+ param: "promptId",
+ },
+});
+
const routeTree = rootRoute.addChildren([
workspaceGuardPartialLayoutRoute.addChildren([
getStartedRoute,
@@ -221,7 +231,7 @@ const routeTree = rootRoute.addChildren([
datasetsListRoute,
datasetRoute.addChildren([datasetItemsRoute]),
]),
- promptsRoute.addChildren([promptsListRoute]),
+ promptsRoute.addChildren([promptsListRoute, promptRoute]),
]),
]),
]);
diff --git a/apps/opik-frontend/src/types/prompts.ts b/apps/opik-frontend/src/types/prompts.ts
index ee174ddbd..301be6805 100644
--- a/apps/opik-frontend/src/types/prompts.ts
+++ b/apps/opik-frontend/src/types/prompts.ts
@@ -5,4 +5,21 @@ export interface Prompt {
last_updated_at: string;
created_at: string;
versions_count: number;
+
+ latest_version?: PromptVersion;
+}
+
+export type PromptWithLatestVersion = Prompt & {
+ latest_version?: PromptVersion;
+};
+
+export interface PromptVersion {
+ id: string;
+ created_at: string;
+ template: string;
+}
+
+export interface CompactPromptVersion {
+ id: string;
+ created_at: string;
}
From 6cb04b4caa149adc5e5340b2087cb9ca83104596 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Tue, 5 Nov 2024 14:46:26 +0100
Subject: [PATCH 22/45] [OPIK-349]: eslint issues;
---
.../prompts/useCreatePromptVersionMutation.ts | 18 +++++++-----------
.../CompareExperimentsDetails.tsx | 9 +--------
.../pages/PromptPage/PromptTab/PromptTab.tsx | 2 +-
3 files changed, 9 insertions(+), 20 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
index a93333f04..6cd1cf395 100644
--- a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
@@ -5,22 +5,18 @@ import get from "lodash/get";
import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
import { useToast } from "@/components/ui/use-toast";
-type UseCreatePromptVersionMutationParams = {
- name: string;
- id: string;
- template: string;
-};
+// type UseCreatePromptVersionMutationParams = {
+// name: string;
+// id: string;
+// template: string;
+// };
const useCreatePromptVersionMutation = () => {
const queryClient = useQueryClient();
const { toast } = useToast();
return useMutation({
- mutationFn: async ({
- name,
- id,
- template,
- }: UseCreatePromptVersionMutationParams) => {
+ mutationFn: async () => {
const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}/versions`, {
...prompt,
});
@@ -40,7 +36,7 @@ const useCreatePromptVersionMutation = () => {
variant: "destructive",
});
},
- onSettled: (data, error, variables, context) => {
+ onSettled: () => {
return queryClient.invalidateQueries({ queryKey: ["prompt-versions"] });
},
});
diff --git a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
index 693766cc4..c175d0cea 100644
--- a/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
+++ b/apps/opik-frontend/src/components/pages/CompareExperimentsPage/CompareExperimentsDetails.tsx
@@ -3,20 +3,13 @@ import sortBy from "lodash/sortBy";
import uniq from "lodash/uniq";
import isUndefined from "lodash/isUndefined";
import { BooleanParam, useQueryParam } from "use-query-params";
-import {
- Clock,
- FlaskConical,
- Maximize2,
- Minimize2,
- PenLine,
-} from "lucide-react";
+import { FlaskConical, Maximize2, Minimize2, PenLine } from "lucide-react";
import useBreadcrumbsStore from "@/store/BreadcrumbsStore";
import FeedbackScoreTag from "@/components/shared/FeedbackScoreTag/FeedbackScoreTag";
import { Experiment } from "@/types/datasets";
import { TableBody, TableCell, TableRow } from "@/components/ui/table";
import { Tag } from "@/components/ui/tag";
-import { formatDate } from "@/lib/date";
import { Button } from "@/components/ui/button";
import ResourceLink, {
RESOURCE_TYPE,
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 293b49ce2..fb76ecfff 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -1,4 +1,4 @@
-import React, { useMemo, useRef, useState } from "react";
+import React, { useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Info, Pencil } from "lucide-react";
From 20555793f1d2ba1e28358fb4a21092791b0ca4cc Mon Sep 17 00:00:00 2001
From: Sasha
Date: Tue, 5 Nov 2024 17:24:49 +0100
Subject: [PATCH 23/45] [OPIK-351]: finished commits tab;
---
...rsionsById.ts => usePromptVersionsById.ts} | 0
.../pages/PromptPage/PromptPage.tsx | 9 +-
.../pages/PromptPage/PromptTab/CommitsTab.tsx | 109 ++++++++++++++++++
.../pages/PromptPage/PromptTab/PromptTab.tsx | 2 +-
.../pages/PromptsPage/PromptsPage.tsx | 6 +-
5 files changed, 119 insertions(+), 7 deletions(-)
rename apps/opik-frontend/src/api/prompts/{usePromptsVersionsById.ts => usePromptVersionsById.ts} (100%)
create mode 100644 apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts b/apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts
similarity index 100%
rename from apps/opik-frontend/src/api/prompts/usePromptsVersionsById.ts
rename to apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
index f59d67e45..326761659 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
@@ -7,6 +7,7 @@ import { usePromptIdFromURL } from "@/hooks/usePromptIdFromURL";
import usePromptById from "@/api/prompts/usePromptById";
import DateTag from "@/components/shared/DateTag/DateTag";
import PromptTab from "@/components/pages/PromptPage/PromptTab/PromptTab";
+import CommitsTab from "@/components/pages/PromptPage/PromptTab/CommitsTab";
const PromptPage: React.FunctionComponent = () => {
const [tab, setTab] = useQueryParam("tab", StringParam, {
@@ -23,13 +24,13 @@ const PromptPage: React.FunctionComponent = () => {
if (promptId && promptName) {
setBreadcrumbParam("promptId", promptId, promptName);
}
- }, [promptId, promptName]);
+ }, [promptId, promptName, setBreadcrumbParam]);
useEffect(() => {
if (!tab) {
setTab("prompt");
}
- }, [tab]);
+ }, [tab, setTab]);
return (
@@ -61,7 +62,9 @@ const PromptPage: React.FunctionComponent = () => {
Experiments
-
Commits
+
+
+
);
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
new file mode 100644
index 000000000..d490c66f4
--- /dev/null
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
@@ -0,0 +1,109 @@
+import React, { useCallback, useMemo, useState } from "react";
+
+import { CompactPromptVersion, PromptWithLatestVersion } from "@/types/prompts";
+import Loader from "@/components/shared/Loader/Loader";
+import usePromptVersionsById from "@/api/prompts/usePromptVersionsById";
+
+import { useNavigate } from "@tanstack/react-router";
+import useAppStore from "@/store/AppStore";
+import DataTable from "@/components/shared/DataTable/DataTable";
+import DataTableNoData from "@/components/shared/DataTableNoData/DataTableNoData";
+import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
+
+import { COLUMN_TYPE } from "@/types/shared";
+import IdCell from "@/components/shared/DataTableCells/IdCell";
+import { formatDate } from "@/lib/date";
+import { convertColumnDataToColumn } from "@/lib/table";
+import CodeCell from "@/components/shared/DataTableCells/CodeCell";
+
+interface CommitsTabInterface {
+ prompt?: PromptWithLatestVersion;
+}
+
+export const COMMITS_DEFAULT_COLUMNS = convertColumnDataToColumn<
+ CompactPromptVersion,
+ CompactPromptVersion
+>(
+ [
+ {
+ id: "id",
+ label: "Prompt commit",
+ type: COLUMN_TYPE.string,
+ cell: IdCell as never,
+ },
+ {
+ id: "template",
+ label: "Prompt",
+ type: COLUMN_TYPE.dictionary,
+ cell: CodeCell as never,
+ },
+
+ {
+ id: "created_at",
+ label: "Created at",
+ type: COLUMN_TYPE.time,
+ accessorFn: (row) => formatDate(row.created_at),
+ },
+ ],
+ {},
+);
+
+const CommitsTab = ({ prompt }: CommitsTabInterface) => {
+ const navigate = useNavigate();
+
+ const workspaceName = useAppStore((state) => state.activeWorkspaceName);
+
+ const [page, setPage] = useState(1);
+ const [size, setSize] = useState(10);
+
+ const { data } = usePromptVersionsById(
+ {
+ promptId: prompt?.id || "",
+ page: page,
+ size: size,
+ },
+ {
+ enabled: !!prompt?.id,
+ },
+ );
+
+ const versions = data?.content ?? [];
+ const total = data?.total ?? 0;
+ const noDataText = "There are no commits yet";
+
+ const handleRowClick = useCallback((prompt: CompactPromptVersion) => {
+ navigate({
+ to: "/$workspaceName/prompts/$promptId",
+ params: {
+ promptId: prompt.id,
+ workspaceName,
+ },
+ });
+ }, []);
+
+ if (!versions) {
+ return ;
+ }
+
+ return (
+
+ );
+};
+
+export default CommitsTab;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index fb76ecfff..94928f3f2 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
import { Info, Pencil } from "lucide-react";
import { PromptWithLatestVersion } from "@/types/prompts";
import Loader from "@/components/shared/Loader/Loader";
-import usePromptVersionsById from "@/api/prompts/usePromptsVersionsById";
+import usePromptVersionsById from "@/api/prompts/usePromptVersionsById";
import UseThisPromptDialog from "@/components/pages/PromptPage/PromptTab/UseThisPromptDialog";
import EditPromptDialog from "@/components/pages/PromptPage/PromptTab/EditPromptDialog";
import CommitHistory from "@/components/pages/PromptPage/PromptTab/CommitHistory";
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 64c7654d7..515f2e890 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -139,7 +139,7 @@ const PromptsPage: React.FunctionComponent = () => {
[setColumnsWidth],
);
- const handleNewDatasetClick = useCallback(() => {
+ const handleNewPromptClick = useCallback(() => {
setOpenDialog(true);
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
@@ -178,7 +178,7 @@ const PromptsPage: React.FunctionComponent = () => {
order={columnsOrder}
onOrderChange={setColumnsOrder}
>
-
+
Create new prompt
@@ -191,7 +191,7 @@ const PromptsPage: React.FunctionComponent = () => {
noData={
{noData && (
-
+
Create new prompt
)}
From 863db6b11fe0b66de4eec31c76f74dbb69814d37 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 10:44:01 +0100
Subject: [PATCH 24/45] [OPIK-351]: add a pending state to commits;
---
.../components/pages/PromptPage/PromptTab/CommitsTab.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
index d490c66f4..d12e7e856 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo, useState } from "react";
+import React, { useCallback, useState } from "react";
import { CompactPromptVersion, PromptWithLatestVersion } from "@/types/prompts";
import Loader from "@/components/shared/Loader/Loader";
@@ -56,7 +56,7 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
- const { data } = usePromptVersionsById(
+ const { data, isPending } = usePromptVersionsById(
{
promptId: prompt?.id || "",
page: page,
@@ -81,7 +81,7 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
});
}, []);
- if (!versions) {
+ if (isPending) {
return ;
}
From ce0943d9b29ba6a06dee6f94b088336b1a6b7350 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 10:51:33 +0100
Subject: [PATCH 25/45] [OPIK-351]: fix the type;
---
.../TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
index 195c78b0a..fde9469fa 100644
--- a/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
+++ b/apps/opik-frontend/src/components/shared/TraceDetailsPanel/TraceAnnotateViewer/AnnotateRow.tsx
@@ -167,7 +167,11 @@ const AnnotateRow: React.FunctionComponent = ({
{!isUndefined(feedbackScore?.value) && (
-
+
)}
From 1038c33b8f0066882d15c8257332a95bee18212c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 12:20:21 +0100
Subject: [PATCH 26/45] [OPIK-319]: finish the integration with the BE;
---
.../prompts/useCreatePromptVersionMutation.ts | 24 ++--
.../src/api/prompts/usePromptById.ts | 31 +----
.../api/prompts/usePromptCreateMutation.ts | 19 +--
.../src/api/prompts/usePromptVersionById.ts | 32 +++++
.../src/api/prompts/usePromptVersionsById.ts | 90 +++----------
.../src/api/prompts/usePromptsList.ts | 123 +++---------------
.../PromptPage/PromptTab/CommitHistory.tsx | 21 ++-
.../pages/PromptPage/PromptTab/CommitsTab.tsx | 33 +++--
.../PromptPage/PromptTab/EditPromptDialog.tsx | 20 ++-
.../pages/PromptPage/PromptTab/PromptTab.tsx | 45 ++++++-
.../pages/PromptsPage/AddPromptDialog.tsx | 3 +-
.../pages/PromptsPage/PromptsPage.tsx | 4 +-
apps/opik-frontend/src/types/prompts.ts | 7 +-
13 files changed, 195 insertions(+), 257 deletions(-)
create mode 100644 apps/opik-frontend/src/api/prompts/usePromptVersionById.ts
diff --git a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
index 6cd1cf395..9fbf107f5 100644
--- a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts
@@ -5,20 +5,25 @@ import get from "lodash/get";
import api, { PROMPTS_REST_ENDPOINT } from "@/api/api";
import { useToast } from "@/components/ui/use-toast";
-// type UseCreatePromptVersionMutationParams = {
-// name: string;
-// id: string;
-// template: string;
-// };
+type UseCreatePromptVersionMutationParams = {
+ name: string;
+ template: string;
+};
const useCreatePromptVersionMutation = () => {
const queryClient = useQueryClient();
const { toast } = useToast();
return useMutation({
- mutationFn: async () => {
- const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}/versions`, {
- ...prompt,
+ mutationFn: async ({
+ name,
+ template,
+ }: UseCreatePromptVersionMutationParams) => {
+ const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}versions`, {
+ name,
+ version: {
+ template,
+ },
});
return data;
@@ -37,7 +42,8 @@ const useCreatePromptVersionMutation = () => {
});
},
onSettled: () => {
- return queryClient.invalidateQueries({ queryKey: ["prompt-versions"] });
+ queryClient.invalidateQueries({ queryKey: ["prompt-versions"] });
+ queryClient.invalidateQueries({ queryKey: ["prompt"] });
},
});
};
diff --git a/apps/opik-frontend/src/api/prompts/usePromptById.ts b/apps/opik-frontend/src/api/prompts/usePromptById.ts
index 818a86aa9..dcd8e8f2b 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptById.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptById.ts
@@ -2,38 +2,15 @@ import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
import { PromptWithLatestVersion } from "@/types/prompts";
-// ALEX
-const FAKE_PROMPT = {
- id: "p001",
- name: "Product Recommendation Prompt",
- description:
- "A prompt designed to generate product recommendations based on user preferences.",
- last_updated_at: "2024-11-04T14:35:00Z",
- created_at: "2024-10-20T09:00:00Z",
- versions_count: 3,
-
- latest_version: {
- id: "v003",
- created_at: "2024-11-04T14:35:00Z",
- template:
- "Recommend products to {{username}} based on preferences in {{category}} and previous interactions.",
- variables: ["username", "category"],
- },
-};
-
const getPromptById = async (
{ signal }: QueryFunctionContext,
{ promptId }: UsePromptByIdParams,
) => {
- try {
- const { data } = await api.get(`${PROMPTS_REST_ENDPOINT}/${promptId}`, {
- signal,
- });
+ const { data } = await api.get(`${PROMPTS_REST_ENDPOINT}${promptId}`, {
+ signal,
+ });
- return data;
- } catch {
- return FAKE_PROMPT;
- }
+ return data;
};
type UsePromptByIdParams = {
diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
index 4ed9e2d63..f953bae01 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts
@@ -12,7 +12,6 @@ interface CreatePromptTemplate {
type UsePromptCreateMutationParams = {
prompt: Partial & CreatePromptTemplate;
- workspaceName: string;
};
const usePromptCreateMutation = () => {
@@ -20,22 +19,14 @@ const usePromptCreateMutation = () => {
const { toast } = useToast();
return useMutation({
- mutationFn: async ({
- prompt,
- workspaceName,
- }: UsePromptCreateMutationParams) => {
+ mutationFn: async ({ prompt }: UsePromptCreateMutationParams) => {
const { data } = await api.post(PROMPTS_REST_ENDPOINT, {
...prompt,
- workspace_name: workspaceName,
});
return data;
},
- onMutate: async (params: UsePromptCreateMutationParams) => {
- return {
- queryKey: ["prompts", { workspaceName: params.workspaceName }],
- };
- },
+
onError: (error: AxiosError) => {
const message = get(
error,
@@ -49,10 +40,8 @@ const usePromptCreateMutation = () => {
variant: "destructive",
});
},
- onSettled: (data, error, variables, context) => {
- if (context) {
- return queryClient.invalidateQueries({ queryKey: context.queryKey });
- }
+ onSettled: () => {
+ return queryClient.invalidateQueries({ queryKey: ["prompts"] });
},
});
};
diff --git a/apps/opik-frontend/src/api/prompts/usePromptVersionById.ts b/apps/opik-frontend/src/api/prompts/usePromptVersionById.ts
new file mode 100644
index 000000000..80eb9baa8
--- /dev/null
+++ b/apps/opik-frontend/src/api/prompts/usePromptVersionById.ts
@@ -0,0 +1,32 @@
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
+import { PromptVersion } from "@/types/prompts";
+
+type UsePromptVersionByIdParams = {
+ versionId: string;
+};
+
+const getPromptVersionById = async (
+ { signal }: QueryFunctionContext,
+ { versionId }: UsePromptVersionByIdParams,
+) => {
+ const { data } = await api.get(
+ `${PROMPTS_REST_ENDPOINT}versions/${versionId}`,
+ {
+ signal,
+ },
+ );
+
+ return data;
+};
+
+export default function usePromptVersionById(
+ params: UsePromptVersionByIdParams,
+ options?: QueryConfig,
+) {
+ return useQuery({
+ queryKey: ["prompt-version", params],
+ queryFn: (context) => getPromptVersionById(context, params),
+ ...options,
+ });
+}
diff --git a/apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts b/apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts
index 99ccdbec4..e60150a5b 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptVersionsById.ts
@@ -1,73 +1,6 @@
import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
-import { CompactPromptVersion } from "@/types/prompts";
-
-// ALEX
-const FAKE_PROMPT_VERSIONS: CompactPromptVersion[] = [
- {
- id: "prompt_1234123412341234123412341241231",
- created_at: "2023-10-01T08:30:00Z",
- },
- {
- id: "prompt_2",
- created_at: "2023-10-02T10:15:00Z",
- },
- {
- id: "prompt_3",
- created_at: "2023-10-03T12:45:00Z",
- },
- {
- id: "prompt_4",
- created_at: "2023-10-04T15:20:00Z",
- },
- {
- id: "prompt_5",
- created_at: "2023-10-05T18:05:00Z",
- },
- {
- id: "prompt_6",
- created_at: "2023-10-06T09:40:00Z",
- },
- {
- id: "prompt_7",
- created_at: "2023-10-07T11:25:00Z",
- },
- {
- id: "prompt_8",
- created_at: "2023-10-08T13:55:00Z",
- },
- {
- id: "prompt_9",
- created_at: "2023-10-09T16:10:00Z",
- },
- {
- id: "prompt_10",
- created_at: "2023-10-10T19:30:00Z",
- },
-];
-
-const getPromptVersionsById = async (
- { signal }: QueryFunctionContext,
- { promptId, size, page, search }: UsePromptVersionsByIdParams,
-) => {
- try {
- const { data } = await api.get(
- `${PROMPTS_REST_ENDPOINT}/${promptId}/versions`,
- {
- signal,
- params: {
- ...(search && { name: search }),
- size,
- page,
- },
- },
- );
-
- return data;
- } catch {
- return { content: FAKE_PROMPT_VERSIONS };
- }
-};
+import { PromptVersion } from "@/types/prompts";
type UsePromptVersionsByIdParams = {
promptId: string;
@@ -77,10 +10,29 @@ type UsePromptVersionsByIdParams = {
};
type UsePromptsVersionsByIdResponse = {
- content: CompactPromptVersion[];
+ content: PromptVersion[];
total: number;
};
+const getPromptVersionsById = async (
+ { signal }: QueryFunctionContext,
+ { promptId, size, page, search }: UsePromptVersionsByIdParams,
+) => {
+ const { data } = await api.get(
+ `${PROMPTS_REST_ENDPOINT}${promptId}/versions`,
+ {
+ signal,
+ params: {
+ ...(search && { name: search }),
+ size,
+ page,
+ },
+ },
+ );
+
+ return data;
+};
+
export default function usePromptVersionsById(
params: UsePromptVersionsByIdParams,
options?: QueryConfig,
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 1cac9fdde..dec072acb 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -1,5 +1,5 @@
-import { useQuery } from "@tanstack/react-query";
-import { QueryConfig } from "@/api/api";
+import { QueryFunctionContext, useQuery } from "@tanstack/react-query";
+import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
import { Prompt } from "@/types/prompts";
type UsePromptsListParams = {
@@ -14,109 +14,22 @@ type UsePromptsListResponse = {
total: number;
};
-// ALEX
-const FAKE_PROMPTS: Prompt[] = [
- {
- id: "4338ec03-6ee9-4635-b071-77849626b948",
- name: "Item 1123421342134341234812349123841239048132094812304123804301294",
- description: "This is a description for Item 1.",
- last_updated_at: "2022-04-15 00:00:00",
- created_at: "2020-09-09 00:00:00",
- versions_count: 6,
- },
- {
- id: "2ac76571-520f-4664-9ad5-1439492ad557",
- name: "Item 2",
- description: "This is a description for Item 2.",
- last_updated_at: "2022-08-19 00:00:00",
- created_at: "2021-10-27 00:00:00",
- versions_count: 4,
- },
- {
- id: "3ba74f16-698f-4318-9427-d26403bc117b",
- name: "Item 3",
- description: "This is a description for Item 3.",
- last_updated_at: "2023-12-12 00:00:00",
- created_at: "2021-10-08 00:00:00",
- versions_count: 5,
- },
- {
- id: "bbef9b6c-d991-4132-9c08-24e1584ccea2",
- name: "Item 4",
- description: "This is a description for Item 4.",
- last_updated_at: "2023-05-14 00:00:00",
- created_at: "2023-01-04 00:00:00",
- versions_count: 10,
- },
- {
- id: "57c82e2b-3d75-4f16-87ac-3201554ea84d",
- name: "Item 5",
- description: "This is a description for Item 5.",
- last_updated_at: "2022-06-10 00:00:00",
- created_at: "2021-10-06 00:00:00",
- versions_count: 4,
- },
- {
- id: "caad2d07-6be4-4e30-8e54-45928c4c675c",
- name: "Item 6",
- description: "This is a description for Item 6.",
- last_updated_at: "2023-11-07 00:00:00",
- created_at: "2022-04-26 00:00:00",
- versions_count: 7,
- },
- {
- id: "955439b8-2199-4edb-bfff-0becef27f477",
- name: "Item 7",
- description: "This is a description for Item 7.",
- last_updated_at: "2023-09-21 00:00:00",
- created_at: "2023-08-15 00:00:00",
- versions_count: 5,
- },
- {
- id: "059452b9-9050-4b99-893f-8e809adae877",
- name: "Item 8",
- description: "This is a description for Item 8.",
- last_updated_at: "2023-04-10 00:00:00",
- created_at: "2022-09-22 00:00:00",
- versions_count: 8,
- },
- {
- id: "c46f907a-7e35-4d35-a482-fb4a7fee3967",
- name: "Item 9",
- description: "This is a description for Item 9.",
- last_updated_at: "2023-12-22 00:00:00",
- created_at: "2023-05-13 00:00:00",
- versions_count: 8,
- },
- {
- id: "c4365771-f654-4434-9272-8e22f623906b",
- name: "Item 10",
- description: "This is a description for Item 10.",
- last_updated_at: "2023-09-09 00:00:00",
- created_at: "2022-12-02 00:00:00",
- versions_count: 6,
- },
-];
-
-const getPromptsList = async () =>
- // { signal }: QueryFunctionContext,
- // { workspaceName, search, size, page }: UsePromptsListParams,
- {
- // const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
- // signal,
- // params: {
- // workspace_name: workspaceName,
- // ...(search && { name: search }),
- // size,
- // page,
- // },
- // });
+const getPromptsList = async (
+ { signal }: QueryFunctionContext,
+ { workspaceName, search, size, page }: UsePromptsListParams,
+) => {
+ const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
+ signal,
+ params: {
+ workspace_name: workspaceName,
+ ...(search && { name: search }),
+ size,
+ page,
+ },
+ });
- return {
- content: FAKE_PROMPTS,
- total: FAKE_PROMPTS.length,
- };
- };
+ return data;
+};
export default function usePromptsList(
params: UsePromptsListParams,
@@ -124,7 +37,7 @@ export default function usePromptsList(
) {
return useQuery({
queryKey: ["prompts", params],
- queryFn: () => getPromptsList(),
+ queryFn: (context) => getPromptsList(context, params),
...options,
});
}
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
index b3ff6dfc5..d8cd977f9 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -1,18 +1,25 @@
import { Copy, GitCommitVertical } from "lucide-react";
import copy from "clipboard-copy";
+import { cn } from "@/lib/utils";
import { formatDate } from "@/lib/date";
import React, { useState } from "react";
-import { CompactPromptVersion } from "@/types/prompts";
import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
import { Button } from "@/components/ui/button";
import { useToast } from "@/components/ui/use-toast";
+import { PromptVersion } from "@/types/prompts";
interface CommitHistoryProps {
- versions: CompactPromptVersion[];
+ versions: PromptVersion[];
+ onVersionClick: (version: PromptVersion) => void;
+ activeVersionId: string;
}
-const CommitHistory = ({ versions }: CommitHistoryProps) => {
+const CommitHistory = ({
+ versions,
+ onVersionClick,
+ activeVersionId,
+}: CommitHistoryProps) => {
const { toast } = useToast();
const [hoveredVersionId, setHoveredVersionId] = useState(null);
@@ -30,9 +37,15 @@ const CommitHistory = ({ versions }: CommitHistoryProps) => {
return (
setHoveredVersionId(version.id)}
onMouseLeave={() => setHoveredVersionId(null)}
+ onClick={() => onVersionClick(version)}
>
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
index d12e7e856..6c430ec25 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useState } from "react";
-import { CompactPromptVersion, PromptWithLatestVersion } from "@/types/prompts";
+import { PromptWithLatestVersion, PromptVersion } from "@/types/prompts";
import Loader from "@/components/shared/Loader/Loader";
import usePromptVersionsById from "@/api/prompts/usePromptVersionsById";
@@ -21,8 +21,8 @@ interface CommitsTabInterface {
}
export const COMMITS_DEFAULT_COLUMNS = convertColumnDataToColumn<
- CompactPromptVersion,
- CompactPromptVersion
+ PromptVersion,
+ PromptVersion
>(
[
{
@@ -71,15 +71,24 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
const total = data?.total ?? 0;
const noDataText = "There are no commits yet";
- const handleRowClick = useCallback((prompt: CompactPromptVersion) => {
- navigate({
- to: "/$workspaceName/prompts/$promptId",
- params: {
- promptId: prompt.id,
- workspaceName,
- },
- });
- }, []);
+ const handleRowClick = useCallback(
+ (version: PromptVersion) => {
+ if (prompt?.id) {
+ navigate({
+ to: `/$workspaceName/prompts/$promptId`,
+ params: {
+ promptId: prompt.id,
+ workspaceName,
+ },
+ // ALEX
+ search: {
+ activeVersionId: version.id,
+ },
+ });
+ }
+ },
+ [prompt?.id],
+ );
if (isPending) {
return
;
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index 1624d29c1..46cc239ee 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -11,22 +11,34 @@ import {
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
+import useCreatePromptVersionMutation from "@/api/prompts/useCreatePromptVersionMutation";
type EditPromptDialogProps = {
open: boolean;
setOpen: (open: boolean) => void;
promptTemplate: string;
- promptId: string;
+ promptName: string;
};
+// ALEX CHECK PROMPT VERSION NAMES EVERYWHERE
const EditPromptDialog: React.FunctionComponent
= ({
open,
setOpen,
promptTemplate: parentPromptTemplate,
+ promptName,
}) => {
const [promptTemplate, setPromptTemplate] = useState(parentPromptTemplate);
+ const createPromptVersionMutation = useCreatePromptVersionMutation();
+
+ const handleClickEditPrompt = () => {
+ createPromptVersionMutation.mutate({
+ name: promptName,
+ template: promptTemplate,
+ });
+ };
+
const isValid =
promptTemplate?.length && promptTemplate !== parentPromptTemplate;
@@ -62,7 +74,11 @@ const EditPromptDialog: React.FunctionComponent = ({
Cancel
-
+
Edit prompt
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 94928f3f2..cfcce6532 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -1,4 +1,4 @@
-import React, { useRef, useState } from "react";
+import React, { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Info, Pencil } from "lucide-react";
@@ -8,6 +8,8 @@ import usePromptVersionsById from "@/api/prompts/usePromptVersionsById";
import UseThisPromptDialog from "@/components/pages/PromptPage/PromptTab/UseThisPromptDialog";
import EditPromptDialog from "@/components/pages/PromptPage/PromptTab/EditPromptDialog";
import CommitHistory from "@/components/pages/PromptPage/PromptTab/CommitHistory";
+import usePromptVersionById from "@/api/prompts/usePromptVersionById";
+import { StringParam, useQueryParam } from "use-query-params";
interface PromptTabInterface {
prompt?: PromptWithLatestVersion;
@@ -16,7 +18,17 @@ interface PromptTabInterface {
const PromptTab = ({ prompt }: PromptTabInterface) => {
const [openUseThisPrompt, setOpenUseThisPrompt] = useState(false);
const [openEditPrompt, setOpenEditPrompt] = useState(false);
+
+ const [activeVersionId, setActiveVersionId] = useQueryParam(
+ "activeVersionId",
+ StringParam,
+ {
+ updateType: "replaceIn",
+ },
+ );
+
const editPromptResetKeyRef = useRef(0);
+
const { data } = usePromptVersionsById(
{
promptId: prompt?.id || "",
@@ -28,6 +40,15 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
},
);
+ const { data: activeVersion } = usePromptVersionById(
+ {
+ versionId: activeVersionId || "",
+ },
+ {
+ enabled: !!activeVersionId,
+ },
+ );
+
const versions = data?.content;
const handleOpenEditPrompt = (value: boolean) => {
@@ -35,6 +56,18 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
setOpenEditPrompt(value);
};
+ useEffect(() => {
+ if (prompt?.latest_version?.id && !activeVersionId) {
+ setActiveVersionId(prompt.latest_version.id);
+ }
+ }, [prompt?.latest_version?.id, activeVersionId]);
+
+ useEffect(() => {
+ return () => {
+ setActiveVersionId(null);
+ };
+ }, []);
+
if (!prompt) {
return ;
}
@@ -58,7 +91,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
Prompt
- {prompt?.latest_version?.template}
+ {activeVersion?.template}
@@ -66,7 +99,11 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
Commit history
-
+ setActiveVersionId(version.id)}
+ />
@@ -80,7 +117,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
key={editPromptResetKeyRef.current}
open={openEditPrompt}
setOpen={handleOpenEditPrompt}
- promptId={prompt.id}
+ promptName={prompt.name}
promptTemplate={prompt.latest_version?.template || ""}
/>
>
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
index 671b8f8d0..a7bfa7194 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddPromptDialog.tsx
@@ -48,12 +48,11 @@ const AddPromptDialog: React.FunctionComponent = ({
template: prompt,
...(description ? { description } : {}),
},
- workspaceName,
},
{ onSuccess: onPromptCreated },
);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [name, description, workspaceName, onPromptCreated]);
+ }, [name, description, workspaceName, prompt, onPromptCreated]);
return (
-
+ {!isEdit && (
+
+ )}
@@ -104,8 +134,8 @@ const AddPromptDialog: React.FunctionComponent = ({
Cancel
-
- Create prompt
+
+ {isEdit ? "Edit prompt" : "Create prompt"}
@@ -114,4 +144,4 @@ const AddPromptDialog: React.FunctionComponent = ({
);
};
-export default AddPromptDialog;
+export default AddEditPromptDialog;
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
index ac77ad530..9fdcfb364 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptRowActionsCell.tsx
@@ -5,19 +5,23 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
-import { MoreHorizontal, Trash } from "lucide-react";
+import { MoreHorizontal, Pencil, Trash } from "lucide-react";
import React, { useCallback, useRef, useState } from "react";
import { CellContext } from "@tanstack/react-table";
import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
import { Prompt } from "@/types/prompts";
import usePromptDeleteMutation from "@/api/prompts/usePromptDeleteMutation";
+import AddEditPromptDialog from "@/components/pages/PromptsPage/AddEditPromptDialog";
+
+const EDIT_KEY = 1;
+const DELETE_KEY = 2;
export const PromptRowActionsCell: React.FunctionComponent<
CellContext
> = ({ row }) => {
const resetKeyRef = useRef(0);
const prompt = row.original;
- const [open, setOpen] = useState(false);
+ const [open, setOpen] = useState(false);
const promptDeleteMutation = usePromptDeleteMutation();
@@ -33,9 +37,16 @@ export const PromptRowActionsCell: React.FunctionComponent<
className="flex size-full items-center justify-end"
onClick={(e) => e.stopPropagation()}
>
+
+
{
- setOpen(true);
+ setOpen(EDIT_KEY);
+ resetKeyRef.current = resetKeyRef.current + 1;
+ }}
+ >
+
+ Edit
+
+
+ {
+ setOpen(DELETE_KEY);
resetKeyRef.current = resetKeyRef.current + 1;
}}
>
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index ebb29b740..36dc2a2e1 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -16,7 +16,7 @@ import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
import usePromptsList from "@/api/prompts/usePromptsList";
import { Prompt } from "@/types/prompts";
import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
-import AddPromptDialog from "@/components/pages/PromptsPage/AddPromptDialog";
+import AddEditPromptDialog from "@/components/pages/PromptsPage/AddEditPromptDialog";
import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
import { useNavigate } from "@tanstack/react-router";
@@ -207,7 +207,7 @@ const PromptsPage: React.FunctionComponent = () => {
total={total}
>
-
Date: Wed, 6 Nov 2024 12:53:34 +0100
Subject: [PATCH 30/45] [OPIK-348]: remove workspace name;
---
.../src/components/pages/PromptsPage/AddEditPromptDialog.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
index 862c28bb9..dbfac6b19 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
@@ -10,7 +10,6 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
-import useAppStore from "@/store/AppStore";
import { Textarea } from "@/components/ui/textarea";
import usePromptCreateMutation from "@/api/prompts/usePromptCreateMutation";
import { Prompt } from "@/types/prompts";
@@ -36,8 +35,6 @@ const AddEditPromptDialog: React.FunctionComponent = ({
onPromptCreated,
prompt: defaultPrompt,
}) => {
- const workspaceName = useAppStore((state) => state.activeWorkspaceName);
-
const [name, setName] = useState(defaultPrompt?.name || "");
const [template, setTemplate] = useState("");
const [description, setDescription] = useState(
From 7c6319b9ce7908189e16aadc1360fee6120d84dc Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 12:56:23 +0100
Subject: [PATCH 31/45] [OPIK-348]: fix the comments;
---
.../PromptPage/PromptTab/EditPromptDialog.tsx | 1 -
.../pages/PromptsPage/AddEditPromptDialog.tsx | 21 +++++++------------
.../pages/PromptsPage/PromptsPage.tsx | 4 ----
3 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index b6c7d61f9..8fbf17b05 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -22,7 +22,6 @@ type EditPromptDialogProps = {
onSetActiveVersionId: (versionId: string) => void;
};
-// ALEX CHECK PROMPT VERSION NAMES EVERYWHERE
const EditPromptDialog: React.FunctionComponent = ({
open,
setOpen,
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
index dbfac6b19..a4de8aa58 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
@@ -21,18 +21,15 @@ import {
} from "@/components/ui/accordion";
import usePromptUpdateMutation from "@/api/prompts/usePromptUpdateMutation";
-// ALEX REMOVE ONPROMPTCREATED
type AddPromptDialogProps = {
open: boolean;
setOpen: (open: boolean) => void;
- onPromptCreated?: (prompt: Prompt) => void;
prompt?: Prompt;
};
const AddEditPromptDialog: React.FunctionComponent = ({
open,
setOpen,
- onPromptCreated,
prompt: defaultPrompt,
}) => {
const [name, setName] = useState(defaultPrompt?.name || "");
@@ -48,18 +45,14 @@ const AddEditPromptDialog: React.FunctionComponent = ({
const isValid = Boolean(name.length && (isEdit || template.length));
const createPrompt = useCallback(() => {
- promptCreateMutation.mutate(
- {
- prompt: {
- name,
- template,
- ...(description ? { description } : {}),
- },
+ promptCreateMutation.mutate({
+ prompt: {
+ name,
+ template,
+ ...(description ? { description } : {}),
},
- // ALEX
- { onSuccess: onPromptCreated },
- );
- }, [name, description, template, onPromptCreated]);
+ });
+ }, [name, description, template]);
const editPrompt = useCallback(() => {
promptUpdateMutation.mutate({
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 36dc2a2e1..0b9f339f1 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -24,10 +24,6 @@ const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
const COLUMNS_WIDTH_KEY = "prompts-columns-width";
const COLUMNS_ORDER_KEY = "prompts-columns-order";
-// ALEX
-// ASK ABOUT PUTTING IT INTO A DIFFERENT HOOK FOR COLUMN STATES
-// ADD A key to the sidebar
-
export const DEFAULT_COLUMNS: ColumnData[] = [
{
id: "id",
From d5c367bec75318fb2d9a4846db8476fa4a23ad8c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 12:58:32 +0100
Subject: [PATCH 32/45] [OPIK-319]: remove tag name cell;
---
.../pages/PromptsPage/PromptsPage.tsx | 2 --
.../pages/PromptsPage/TagNameCell.tsx | 24 -------------------
2 files changed, 26 deletions(-)
delete mode 100644 apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 0b9f339f1..1060894d6 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -17,7 +17,6 @@ import usePromptsList from "@/api/prompts/usePromptsList";
import { Prompt } from "@/types/prompts";
import { PromptRowActionsCell } from "@/components/pages/PromptsPage/PromptRowActionsCell";
import AddEditPromptDialog from "@/components/pages/PromptsPage/AddEditPromptDialog";
-import TagNameCell from "@/components/pages/PromptsPage/TagNameCell";
import { useNavigate } from "@tanstack/react-router";
const SELECTED_COLUMNS_KEY = "prompts-selected-columns";
@@ -35,7 +34,6 @@ export const DEFAULT_COLUMNS: ColumnData[] = [
id: "name",
label: "Name",
type: COLUMN_TYPE.string,
- cell: TagNameCell as never,
},
{
id: "version_count",
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
deleted file mode 100644
index 066421fde..000000000
--- a/apps/opik-frontend/src/components/pages/PromptsPage/TagNameCell.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from "react";
-import { CellContext } from "@tanstack/react-table";
-import { Tag } from "@/components/ui/tag";
-import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
-import { ArrowUpRight } from "lucide-react";
-import { Prompt } from "@/types/prompts";
-
-const TagNameCell = (context: CellContext) => {
- const value = context.getValue();
-
- return (
-
-
- {value}
-
-
-
- );
-};
-
-export default TagNameCell;
From d6239d162b945fa4d169af23cf695e61ffbdb213 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 13:03:53 +0100
Subject: [PATCH 33/45] [OPIK-319]: fix the eslint issues;
---
.../pages/PromptPage/PromptTab/CommitsTab.tsx | 2 +-
.../PromptPage/PromptTab/EditPromptDialog.tsx | 4 ++--
.../pages/PromptPage/PromptTab/PromptTab.tsx | 10 ++++-----
.../pages/PromptsPage/AddEditPromptDialog.tsx | 4 ++--
.../pages/PromptsPage/PromptsPage.tsx | 21 +++++++++++--------
5 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
index ab43b8137..1a7b26fc7 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitsTab.tsx
@@ -86,7 +86,7 @@ const CommitsTab = ({ prompt }: CommitsTabInterface) => {
});
}
},
- [prompt?.id],
+ [prompt?.id, navigate, workspaceName],
);
if (isPending) {
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index 8fbf17b05..87aa80a54 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -46,7 +46,7 @@ const EditPromptDialog: React.FunctionComponent = ({
return (
-
+
Edit prompt
@@ -56,7 +56,7 @@ const EditPromptDialog: React.FunctionComponent = ({
can access older versions of the prompt from the Commits tab.
-
+
-
-
+
+
Prompt
-
+
{activeVersion?.template}
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
index a4de8aa58..908c29fad 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
@@ -52,7 +52,7 @@ const AddEditPromptDialog: React.FunctionComponent
= ({
...(description ? { description } : {}),
},
});
- }, [name, description, template]);
+ }, [name, description, template, promptCreateMutation.mutate]);
const editPrompt = useCallback(() => {
promptUpdateMutation.mutate({
@@ -62,7 +62,7 @@ const AddEditPromptDialog: React.FunctionComponent = ({
...(description ? { description } : {}),
},
});
- }, [name, description, defaultPrompt?.id]);
+ }, [name, description, defaultPrompt?.id, promptUpdateMutation?.mutate]);
const onActionClick = () => {
if (isEdit) {
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 1060894d6..fc0a4f696 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -138,15 +138,18 @@ const PromptsPage: React.FunctionComponent = () => {
resetDialogKeyRef.current = resetDialogKeyRef.current + 1;
}, []);
- const handleRowClick = useCallback((prompt: Prompt) => {
- navigate({
- to: "/$workspaceName/prompts/$promptId",
- params: {
- promptId: prompt.id,
- workspaceName,
- },
- });
- }, []);
+ const handleRowClick = useCallback(
+ (prompt: Prompt) => {
+ navigate({
+ to: "/$workspaceName/prompts/$promptId",
+ params: {
+ promptId: prompt.id,
+ workspaceName,
+ },
+ });
+ },
+ [navigate, workspaceName],
+ );
if (isPending) {
return ;
From 75f5e4c32f11ce2c0addba6f0fc61ee940f35821 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 13:15:00 +0100
Subject: [PATCH 34/45] [OPIK-319]: fix tailwind order;
---
.../pages/PromptPage/PromptTab/CommitHistory.tsx | 6 +++---
.../pages/PromptPage/PromptTab/EditPromptDialog.tsx | 2 +-
.../components/pages/PromptPage/PromptTab/PromptTab.tsx | 8 ++++----
.../components/pages/PromptsPage/AddEditPromptDialog.tsx | 2 ++
4 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
index d8cd977f9..3cee34581 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -32,7 +32,7 @@ const CommitHistory = ({
};
return (
-
+
{versions?.map((version) => {
return (
- onVersionClick(version)}
>
-
+
{version.id}
{hoveredVersionId == version.id && (
@@ -62,7 +62,7 @@ const CommitHistory = ({
)}
-
+
{formatDate(version.created_at)}
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index 87aa80a54..7e7c773e4 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -64,7 +64,7 @@ const EditPromptDialog: React.FunctionComponent = ({
value={promptTemplate}
onChange={(e) => setPromptTemplate(e.target.value)}
/>
-
+
You can specify variables using the "mustache" syntax:{" "}
{"{{variable}}"}.
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 96f8bb572..57cd6089b 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -75,7 +75,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
return (
<>
-
+
setOpenUseThisPrompt(true)}>
Use this prompt
@@ -87,15 +87,15 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
-
+
Prompt
-
+
{activeVersion?.template}
-
+
Commit history
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
index 908c29fad..004cfbaf2 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
@@ -52,6 +52,7 @@ const AddEditPromptDialog: React.FunctionComponent
= ({
...(description ? { description } : {}),
},
});
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [name, description, template, promptCreateMutation.mutate]);
const editPrompt = useCallback(() => {
@@ -62,6 +63,7 @@ const AddEditPromptDialog: React.FunctionComponent = ({
...(description ? { description } : {}),
},
});
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [name, description, defaultPrompt?.id, promptUpdateMutation?.mutate]);
const onActionClick = () => {
From cff5df45925dfe9a2d3295274137066e32815c4c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 13:51:13 +0100
Subject: [PATCH 35/45] [OPIK-319]: hide use this prompt button;
---
.../pages/PromptPage/PromptTab/PromptTab.tsx | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 57cd6089b..4b3d524e6 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
-import { Info, Pencil } from "lucide-react";
+import { Pencil } from "lucide-react";
import { PromptWithLatestVersion } from "@/types/prompts";
import Loader from "@/components/shared/Loader/Loader";
import usePromptVersionsById from "@/api/prompts/usePromptVersionsById";
@@ -76,10 +76,10 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
<>
-
setOpenUseThisPrompt(true)}>
-
- Use this prompt
-
+ {/*
setOpenUseThisPrompt(true)}>*/}
+ {/* */}
+ {/* Use this prompt*/}
+ {/**/}
setOpenEditPrompt(true)}>
From 286c0683c5c84eb92f698f5a7dbb5d9cdf509eec Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 13:52:02 +0100
Subject: [PATCH 36/45] [OPIK-319]: hide the experiments tab;
---
.../src/components/pages/PromptPage/PromptPage.tsx | 4 ----
1 file changed, 4 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
index 326761659..b661b4c2c 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
@@ -51,9 +51,6 @@ const PromptPage: React.FunctionComponent = () => {
Prompt
-
- Experiments
-
Commits
@@ -61,7 +58,6 @@ const PromptPage: React.FunctionComponent = () => {
- Experiments
From c3a6bb2497ec68f57ae4de84319bb132146eb5ab Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 16:51:59 +0100
Subject: [PATCH 37/45] [OPIK-319]: PR comments;
---
.../src/api/prompts/usePromptUpdateMutation.ts | 7 ++++---
.../src/api/prompts/usePromptsList.ts | 4 +---
.../src/components/layout/SideBar/SideBar.tsx | 3 +--
.../pages/PromptsPage/AddEditPromptDialog.tsx | 14 ++++++--------
4 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptUpdateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptUpdateMutation.ts
index d57718b1c..84ed4cc1e 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptUpdateMutation.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptUpdateMutation.ts
@@ -18,9 +18,10 @@ const usePromptUpdateMutation = () => {
mutationFn: async ({ prompt }: UsePromptUpdateMutationParams) => {
const { id: promptId, ...restPrompt } = prompt;
- const { data } = await api.put(`${PROMPTS_REST_ENDPOINT}${promptId}`, {
- ...restPrompt,
- });
+ const { data } = await api.put(
+ `${PROMPTS_REST_ENDPOINT}${promptId}`,
+ restPrompt,
+ );
return data;
},
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index dec072acb..86a04256e 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -3,7 +3,6 @@ import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
import { Prompt } from "@/types/prompts";
type UsePromptsListParams = {
- workspaceName: string;
search?: string;
page: number;
size: number;
@@ -16,12 +15,11 @@ type UsePromptsListResponse = {
const getPromptsList = async (
{ signal }: QueryFunctionContext,
- { workspaceName, search, size, page }: UsePromptsListParams,
+ { search, size, page }: UsePromptsListParams,
) => {
const { data } = await api.get(PROMPTS_REST_ENDPOINT, {
signal,
params: {
- workspace_name: workspaceName,
...(search && { name: search }),
size,
page,
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 1bd7b916f..46396c607 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -216,7 +216,6 @@ const SideBar: React.FunctionComponent = ({
const { data: promptsData } = usePromptsList(
{
- workspaceName,
page: 1,
size: 1,
},
@@ -315,7 +314,7 @@ const SideBar: React.FunctionComponent = ({
}
return (
-
+
{itemElement}
);
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
index 004cfbaf2..8bdc379db 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/AddEditPromptDialog.tsx
@@ -38,33 +38,31 @@ const AddEditPromptDialog: React.FunctionComponent = ({
defaultPrompt?.description || "",
);
- const promptCreateMutation = usePromptCreateMutation();
- const promptUpdateMutation = usePromptUpdateMutation();
+ const { mutate: createMutate } = usePromptCreateMutation();
+ const { mutate: updateMutate } = usePromptUpdateMutation();
const isEdit = !!defaultPrompt;
const isValid = Boolean(name.length && (isEdit || template.length));
const createPrompt = useCallback(() => {
- promptCreateMutation.mutate({
+ createMutate({
prompt: {
name,
template,
...(description ? { description } : {}),
},
});
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [name, description, template, promptCreateMutation.mutate]);
+ }, [name, description, template, createMutate]);
const editPrompt = useCallback(() => {
- promptUpdateMutation.mutate({
+ updateMutate({
prompt: {
id: defaultPrompt?.id,
name,
...(description ? { description } : {}),
},
});
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [name, description, defaultPrompt?.id, promptUpdateMutation?.mutate]);
+ }, [name, description, defaultPrompt?.id, updateMutate]);
const onActionClick = () => {
if (isEdit) {
From 0753819cd572358aa35743dbc406854adaebc56c Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 16:59:36 +0100
Subject: [PATCH 38/45] [OPIK-319]: update queries init logic;
---
.../src/components/pages/PromptPage/PromptPage.tsx | 6 ++----
.../src/components/pages/PromptPage/PromptTab/PromptTab.tsx | 5 +----
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
index b661b4c2c..981aba1c2 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptPage.tsx
@@ -10,9 +10,7 @@ import PromptTab from "@/components/pages/PromptPage/PromptTab/PromptTab";
import CommitsTab from "@/components/pages/PromptPage/PromptTab/CommitsTab";
const PromptPage: React.FunctionComponent = () => {
- const [tab, setTab] = useQueryParam("tab", StringParam, {
- updateType: "replaceIn",
- });
+ const [tab, setTab] = useQueryParam("tab", StringParam);
const promptId = usePromptIdFromURL();
@@ -28,7 +26,7 @@ const PromptPage: React.FunctionComponent = () => {
useEffect(() => {
if (!tab) {
- setTab("prompt");
+ setTab("prompt", "replaceIn");
}
}, [tab, setTab]);
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 4b3d524e6..b636df830 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -22,9 +22,6 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
const [activeVersionId, setActiveVersionId] = useQueryParam(
"activeVersionId",
StringParam,
- {
- updateType: "replaceIn",
- },
);
const editPromptResetKeyRef = useRef(0);
@@ -58,7 +55,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
useEffect(() => {
if (prompt?.latest_version?.id && !activeVersionId) {
- setActiveVersionId(prompt.latest_version.id);
+ setActiveVersionId(prompt.latest_version.id, "replaceIn");
}
}, [prompt?.latest_version?.id, activeVersionId, setActiveVersionId]);
From db7359581907e04f201880d762c7538dd1e0e6a1 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 17:07:07 +0100
Subject: [PATCH 39/45] [OPIK-319]: update the order of tailwand;
---
.../components/pages/PromptPage/PromptTab/CommitHistory.tsx | 6 +++---
.../pages/PromptPage/PromptTab/EditPromptDialog.tsx | 2 +-
.../src/components/pages/PromptPage/PromptTab/PromptTab.tsx | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
index 3cee34581..3b6a7d1a5 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -32,7 +32,7 @@ const CommitHistory = ({
};
return (
-
+
{versions?.map((version) => {
return (
- onVersionClick(version)}
>
-
+
{version.id}
{hoveredVersionId == version.id && (
@@ -62,7 +62,7 @@ const CommitHistory = ({
)}
-
+
{formatDate(version.created_at)}
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index 7e7c773e4..c8d0ce557 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -64,7 +64,7 @@ const EditPromptDialog: React.FunctionComponent = ({
value={promptTemplate}
onChange={(e) => setPromptTemplate(e.target.value)}
/>
-
+
You can specify variables using the "mustache" syntax:{" "}
{"{{variable}}"}.
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index b636df830..d92a24d55 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -87,7 +87,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
Prompt
-
+
{activeVersion?.template}
From df064dc9eeb145bcd94a30a1b1824207ea7daa88 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 18:21:37 +0100
Subject: [PATCH 40/45] [OPIK-319]: fix the tailwind issues;
---
.../pages/PromptPage/PromptTab/CommitHistory.tsx | 6 +++---
.../pages/PromptPage/PromptTab/EditPromptDialog.tsx | 2 +-
.../pages/PromptPage/PromptTab/PromptTab.tsx | 10 +++++-----
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
index 3b6a7d1a5..d0c2998d9 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/CommitHistory.tsx
@@ -32,7 +32,7 @@ const CommitHistory = ({
};
return (
-
+
{versions?.map((version) => {
return (
- onVersionClick(version)}
>
-
+
{version.id}
{hoveredVersionId == version.id && (
@@ -62,7 +62,7 @@ const CommitHistory = ({
)}
-
+
{formatDate(version.created_at)}
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
index c8d0ce557..4ba38a382 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx
@@ -64,7 +64,7 @@ const EditPromptDialog: React.FunctionComponent = ({
value={promptTemplate}
onChange={(e) => setPromptTemplate(e.target.value)}
/>
-
+
You can specify variables using the "mustache" syntax:{" "}
{"{{variable}}"}.
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index d92a24d55..3eea80a06 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -72,7 +72,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
return (
<>
-
+
{/* setOpenUseThisPrompt(true)}>*/}
{/* */}
{/* Use this prompt*/}
@@ -84,15 +84,15 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
-
-
+
+
Prompt
-
+
{activeVersion?.template}
-
+
Commit history
From 87c7111479a9c947bd3affd52246ac62d7bb1d02 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 18:24:28 +0100
Subject: [PATCH 41/45] [OPIK-319]: remove workspace name;
---
.../src/components/pages/PromptsPage/PromptsPage.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index fc0a4f696..00408f665 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -72,7 +72,6 @@ const PromptsPage: React.FunctionComponent = () => {
const [size, setSize] = useState(10);
const { data, isPending } = usePromptsList(
{
- workspaceName,
search,
page,
size,
From 86ad293886697854fdc66124ae1700a4dd35e414 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 18:27:53 +0100
Subject: [PATCH 42/45] [OPIK-319]: fix the style;
---
.../components/pages/PromptPage/PromptTab/PromptTab.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 3eea80a06..c7080151e 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -72,13 +72,17 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
return (
<>
-
+
{/*
setOpenUseThisPrompt(true)}>*/}
{/* */}
{/* Use this prompt*/}
{/**/}
-
setOpenEditPrompt(true)}>
+ setOpenEditPrompt(true)}
+ >
Edit prompt
From 8fcf155290d2b79bf757d4a348710fa076a9c5d7 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Wed, 6 Nov 2024 18:31:13 +0100
Subject: [PATCH 43/45] [OPIK-319]: fix the break logic;
---
.../src/components/pages/PromptPage/PromptTab/PromptTab.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index c7080151e..7812b0f79 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -91,7 +91,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
Prompt
-
+
{activeVersion?.template}
From 5a6a0ea0bda4a53ca3f6471293afe823a6ca7e89 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Thu, 7 Nov 2024 09:19:33 +0100
Subject: [PATCH 44/45] [OPIK-319]: add workspace name;
---
apps/opik-frontend/src/api/prompts/usePromptsList.ts | 1 +
apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx | 1 +
.../src/components/pages/PromptsPage/PromptsPage.tsx | 1 +
3 files changed, 3 insertions(+)
diff --git a/apps/opik-frontend/src/api/prompts/usePromptsList.ts b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
index 86a04256e..2c5c2b56a 100644
--- a/apps/opik-frontend/src/api/prompts/usePromptsList.ts
+++ b/apps/opik-frontend/src/api/prompts/usePromptsList.ts
@@ -3,6 +3,7 @@ import api, { PROMPTS_REST_ENDPOINT, QueryConfig } from "@/api/api";
import { Prompt } from "@/types/prompts";
type UsePromptsListParams = {
+ workspaceName: string;
search?: string;
page: number;
size: number;
diff --git a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
index 46396c607..dae8a1e4b 100644
--- a/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
+++ b/apps/opik-frontend/src/components/layout/SideBar/SideBar.tsx
@@ -216,6 +216,7 @@ const SideBar: React.FunctionComponent = ({
const { data: promptsData } = usePromptsList(
{
+ workspaceName,
page: 1,
size: 1,
},
diff --git a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
index 00408f665..fc0a4f696 100644
--- a/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptsPage/PromptsPage.tsx
@@ -72,6 +72,7 @@ const PromptsPage: React.FunctionComponent = () => {
const [size, setSize] = useState(10);
const { data, isPending } = usePromptsList(
{
+ workspaceName,
search,
page,
size,
From beb0be62c6b6d4f29e10699e3f8e2c4b572d1a94 Mon Sep 17 00:00:00 2001
From: Sasha
Date: Thu, 7 Nov 2024 09:30:51 +0100
Subject: [PATCH 45/45] [OPIK-319]: set adding a key to the modal;
---
.../src/components/pages/PromptPage/PromptTab/PromptTab.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
index 7812b0f79..b6eb8bc19 100644
--- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
+++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/PromptTab.tsx
@@ -49,7 +49,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
const versions = data?.content;
const handleOpenEditPrompt = (value: boolean) => {
- editPromptResetKeyRef.current += 1;
+ editPromptResetKeyRef.current = editPromptResetKeyRef.current + 1;
setOpenEditPrompt(value);
};
@@ -81,7 +81,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
setOpenEditPrompt(true)}
+ onClick={() => handleOpenEditPrompt(true)}
>
Edit prompt
@@ -119,7 +119,7 @@ const PromptTab = ({ prompt }: PromptTabInterface) => {
open={openEditPrompt}
setOpen={handleOpenEditPrompt}
promptName={prompt.name}
- promptTemplate={prompt.latest_version?.template || ""}
+ promptTemplate={activeVersion?.template || ""}
onSetActiveVersionId={setActiveVersionId}
/>
>