diff --git a/agenta-web/src/components/Sidebar/config.tsx b/agenta-web/src/components/Sidebar/config.tsx index bdf9a25a6..dd698347c 100644 --- a/agenta-web/src/components/Sidebar/config.tsx +++ b/agenta-web/src/components/Sidebar/config.tsx @@ -55,11 +55,18 @@ export const useSidebarConfig = () => { const sidebarConfig: SidebarConfig[] = [ { - key: "app-management-link", - title: "App Management", + key: "application-link", + title: "Applications", tooltip: "Create new applications or switch between your existing projects.", link: "/apps", icon: , + }, + { + key: "app-testsets-link", + title: "Test Sets", + tooltip: "Create and manage testsets for evaluation purposes.", + link: `/apps/testsets`, + icon: , divider: true, }, { @@ -84,14 +91,6 @@ export const useSidebarConfig = () => { icon: , isHidden: !appId && !recentlyVisitedAppId, }, - { - key: "app-testsets-link", - title: "Test Sets", - tooltip: "Create and manage testsets for evaluation purposes.", - link: `/apps/${appId || recentlyVisitedAppId}/testsets`, - icon: , - isHidden: !appId && !recentlyVisitedAppId, - }, { key: "app-evaluations-link", title: "Evaluations", diff --git a/agenta-web/src/components/TestSetTable/TestsetTable.tsx b/agenta-web/src/components/TestSetTable/TestsetTable.tsx index 872076b7c..6d4b14304 100644 --- a/agenta-web/src/components/TestSetTable/TestsetTable.tsx +++ b/agenta-web/src/components/TestSetTable/TestsetTable.tsx @@ -19,6 +19,7 @@ import {NoticeType} from "antd/es/message/interface" import {GenericObject, KeyValuePair} from "@/lib/Types" import TableCellsRenderer from "./TableCellsRenderer" import TableHeaderComponent from "./TableHeaderComponent" +import {useAppsData} from "@/contexts/app.context" type TestsetTableProps = { mode: "create" | "edit" @@ -93,8 +94,9 @@ const TestsetTable: React.FC = ({mode}) => { const classes = useStylesTestset() const router = useRouter() const {appTheme} = useAppTheme() + const {apps, isLoading: isAppsLoading} = useAppsData() - const appId = router.query.app_id as string + const appId = apps[0]?.app_id const {testset_id} = router.query useBlockNavigation(unSavedChanges, { @@ -115,6 +117,13 @@ const TestsetTable: React.FC = ({mode}) => { } }, [rowData, testsetName, columnDefs, inputValues]) + useEffect(() => { + if ((apps.length === 0 || !apps) && !isAppsLoading) { + message.warning("To view the test set, you first need to create an app.") + router.push("/apps") + } + }, [isAppsLoading]) + useEffect(() => { async function applyColData(colData: {field: string}[] = []) { const newColDefs = createNewColDefs(colData) diff --git a/agenta-web/src/lib/helpers/evaluate.ts b/agenta-web/src/lib/helpers/evaluate.ts index 9fd97f3cf..f1b796cd5 100644 --- a/agenta-web/src/lib/helpers/evaluate.ts +++ b/agenta-web/src/lib/helpers/evaluate.ts @@ -239,7 +239,14 @@ export const getVotesPercentage = (record: HumanEvaluationListTableDataType, ind export const checkIfResourceValidForDeletion = async ( data: Omit[0], "appId">, ) => { - const appId = getAppValues().currentApp?.app_id + let appId + + if (data.resourceType === "testset") { + appId = getAppValues().apps[0]?.app_id + } else { + appId = getAppValues().currentApp?.app_id + } + if (!appId) return false const response = await fetchEvaluatonIdsByResource({...data, appId}) diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/new/endpoint/index.tsx b/agenta-web/src/pages/apps/[app_id]/testsets/new/endpoint/index.tsx deleted file mode 100644 index 673706a4d..000000000 --- a/agenta-web/src/pages/apps/[app_id]/testsets/new/endpoint/index.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import axios from "@/lib/helpers/axiosConfig" -import {getAgentaApiUrl} from "@/lib/helpers/utils" -import {Alert, Button, Form, Input, Spin, Typography, message} from "antd" -import {useRouter} from "next/router" -import {useState} from "react" -import {createUseStyles} from "react-jss" - -const useStyles = createUseStyles({ - container: { - display: "flex", - flexDirection: "column", - rowGap: 20, - maxWidth: 800, - }, - json: { - overflow: "auto", - }, - buttonContainer: { - display: "flex", - flexDirection: "row", - justifyContent: "flex-end", - }, -}) - -type FieldType = { - name: string - endpoint: string -} - -export default function ImportTestsetFromEndpoint() { - const classes = useStyles() - - const router = useRouter() - const appId = router.query.app_id as string - - const handleSubmit = async (values: FieldType) => { - if (values.name.trim() === "" || values.endpoint.trim() === "") { - message.error("Please fill out all fields") - return - } - - setUploadLoading(true) - - const formData = new FormData() - formData.append("endpoint", values.endpoint) - formData.append("testset_name", values.name) - formData.append("app_id", appId) - - try { - // TODO: move to api.ts - await axios.post(`${getAgentaApiUrl()}/api/testsets/endpoint/`, formData, { - headers: {"Content-Type": "multipart/form-data"}, - }) - router.push(`/apps/${appId}/testsets`) - } catch (_) { - // Errors will be handled by Axios interceptor - // Do nothing here - } finally { - setUploadLoading(false) - } - } - - const [uploadLoading, setUploadLoading] = useState(false) - - return ( -
- Import a new Test Set from an endpoint - - - Currently, we only support the JSON format which must meet the following - requirements: -
    -
  1. A JSON with an array of rows
  2. -
  3. - Each row in the array should be an object of column header name as - key and row data as value -
  4. -
- Here is an example of a valid JSON file: -
-                            {JSON.stringify(
-                                [
-                                    {
-                                        recipe_name: "Chicken Parmesan",
-                                        correct_answer: "Chicken",
-                                    },
-                                    {recipe_name: "a, special, recipe", correct_answer: "Beef"},
-                                ],
-                                null,
-                                2,
-                            )}
-                        
- - } - type="info" - /> - - -
- - label="Test Set Name" - name="name" - rules={[{required: true, type: "string", whitespace: true}]} - > - - - - - label="Test Set Endpoint" - name="endpoint" - rules={[{required: true, type: "url"}]} - > - - - -
- -
- -
-
- ) -} diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/[testset_id]/index.tsx b/agenta-web/src/pages/apps/testsets/[testset_id]/index.tsx similarity index 100% rename from agenta-web/src/pages/apps/[app_id]/testsets/[testset_id]/index.tsx rename to agenta-web/src/pages/apps/testsets/[testset_id]/index.tsx diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/index.tsx b/agenta-web/src/pages/apps/testsets/index.tsx similarity index 80% rename from agenta-web/src/pages/apps/[app_id]/testsets/index.tsx rename to agenta-web/src/pages/apps/testsets/index.tsx index ab165ebd1..428f81d6d 100644 --- a/agenta-web/src/pages/apps/[app_id]/testsets/index.tsx +++ b/agenta-web/src/pages/apps/testsets/index.tsx @@ -1,4 +1,4 @@ -import {Button, Table, Space} from "antd" +import {Button, Table, Space, message} from "antd" import Link from "next/link" import {useRouter} from "next/router" import {ColumnsType} from "antd/es/table" @@ -8,8 +8,9 @@ import {DeleteOutlined} from "@ant-design/icons" import {deleteTestsets, useLoadTestsetsList} from "@/services/testsets/api" import {createUseStyles} from "react-jss" import {testset} from "@/lib/Types" -import {isDemo} from "@/lib/helpers/utils" import {checkIfResourceValidForDeletion} from "@/lib/helpers/evaluate" +import {useAppsData} from "@/contexts/app.context" +import {useUpdateEffect} from "usehooks-ts" const useStyles = createUseStyles({ container: { @@ -42,10 +43,18 @@ const useStyles = createUseStyles({ export default function Testsets() { const classes = useStyles() const router = useRouter() - const appId = router.query.app_id as string + const {apps, isLoading: isAppsLoading} = useAppsData() + const appId = apps[0]?.app_id const [selectedRowKeys, setSelectedRowKeys] = useState([]) const {testsets, isTestsetsLoading, mutate} = useLoadTestsetsList(appId) + useUpdateEffect(() => { + if ((apps.length === 0 || !apps) && !isAppsLoading) { + message.warning("To view the test set, you first need to create an app.") + router.push("/apps") + } + }, [isAppsLoading]) + const columns: ColumnsType = [ { title: "Name", @@ -80,6 +89,7 @@ export default function Testsets() { })) ) return + await deleteTestsets(testsetsIds) mutate() setSelectedRowKeys([]) @@ -91,29 +101,15 @@ export default function Testsets() {
- + - + - + - {!isDemo() && ( - - - - )}
{testsets.length > 0 && ( @@ -155,10 +151,10 @@ export default function Testsets() { columns={columns} dataSource={testsets} rowKey="_id" - loading={isTestsetsLoading} + loading={isTestsetsLoading || isAppsLoading} onRow={(record) => { return { - onClick: () => router.push(`/apps/${appId}/testsets/${record._id}`), + onClick: () => router.push(`/apps/testsets/${record._id}`), } }} /> diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/new/api/index.tsx b/agenta-web/src/pages/apps/testsets/new/api/index.tsx similarity index 94% rename from agenta-web/src/pages/apps/[app_id]/testsets/new/api/index.tsx rename to agenta-web/src/pages/apps/testsets/new/api/index.tsx index 829788c3e..b25197315 100644 --- a/agenta-web/src/pages/apps/[app_id]/testsets/new/api/index.tsx +++ b/agenta-web/src/pages/apps/testsets/new/api/index.tsx @@ -8,9 +8,9 @@ import pythonCodeUpload from "@/code_snippets/testsets/create_with_upload/python import cURLCodeUpload from "@/code_snippets/testsets/create_with_upload/curl" import tsCodeUpload from "@/code_snippets/testsets/create_with_upload/typescript" import {Typography} from "antd" -import {useRouter} from "next/router" import {createUseStyles} from "react-jss" import {getAgentaApiUrl} from "@/lib/helpers/utils" +import { useAppsData } from "@/contexts/app.context" const useStyles = createUseStyles({ title: { @@ -20,8 +20,8 @@ const useStyles = createUseStyles({ export default function NewTestsetWithAPI() { const classes = useStyles() - const router = useRouter() - const appId = router.query.app_id as string + const {apps} = useAppsData() + const appId = apps[0]?.app_id const uploadURI = `${getAgentaApiUrl()}/api/testsets/upload` const jsonURI = `${getAgentaApiUrl()}/api/testsets/${appId}` diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/new/manual/index.tsx b/agenta-web/src/pages/apps/testsets/new/manual/index.tsx similarity index 100% rename from agenta-web/src/pages/apps/[app_id]/testsets/new/manual/index.tsx rename to agenta-web/src/pages/apps/testsets/new/manual/index.tsx diff --git a/agenta-web/src/pages/apps/[app_id]/testsets/new/upload/index.tsx b/agenta-web/src/pages/apps/testsets/new/upload/index.tsx similarity index 96% rename from agenta-web/src/pages/apps/[app_id]/testsets/new/upload/index.tsx rename to agenta-web/src/pages/apps/testsets/new/upload/index.tsx index 0b8ecb2f7..024f20140 100644 --- a/agenta-web/src/pages/apps/[app_id]/testsets/new/upload/index.tsx +++ b/agenta-web/src/pages/apps/testsets/new/upload/index.tsx @@ -8,6 +8,7 @@ import {isValidCSVFile, isValidJSONFile} from "@/lib/helpers/fileManipulations" import {GenericObject} from "@/lib/Types" import {globalErrorHandler} from "@/lib/helpers/errorHandler" import {getAgentaApiUrl} from "@/lib/helpers/utils" +import {useAppsData} from "@/contexts/app.context" const useStyles = createUseStyles({ fileFormatBtn: { @@ -29,12 +30,17 @@ const useStyles = createUseStyles({ export default function AddANewTestset() { const classes = useStyles() const router = useRouter() - const appId = router.query.app_id as string + const {apps} = useAppsData() + const appId = apps[0]?.app_id const [form] = Form.useForm() const [uploadLoading, setUploadLoading] = useState(false) const [uploadType, setUploadType] = useState<"JSON" | "CSV" | undefined>("CSV") const onFinish = async (values: any) => { + if (!appId) { + message.warning("To view the test set, you first need to create an app.") + } + const {file} = values const fileObj = file[0].originFileObj const malformedFileError = `The file you uploaded is either malformed or is not a valid ${uploadType} file` @@ -67,7 +73,7 @@ export default function AddANewTestset() { _ignoreError: true, }) form.resetFields() - router.push(`/apps/${appId}/testsets`) + router.push(`/apps/testsets`) } catch (e: any) { if ( e?.response?.data?.detail?.find((item: GenericObject) => diff --git a/agenta-web/src/services/testsets/api/index.ts b/agenta-web/src/services/testsets/api/index.ts index b4806ccc1..3853c2215 100644 --- a/agenta-web/src/services/testsets/api/index.ts +++ b/agenta-web/src/services/testsets/api/index.ts @@ -12,7 +12,7 @@ import {axiosFetcher} from "@/services/api" export const useLoadTestsetsList = (appId: string) => { const {data, error, mutate, isLoading} = useSWR( - `${getAgentaApiUrl()}/api/testsets/?app_id=${appId}`, + () => (appId ? `${getAgentaApiUrl()}/api/testsets/?app_id=${appId}` : null), axiosFetcher, {revalidateOnFocus: false, shouldRetryOnError: false}, )