diff --git a/apps/opik-frontend/src/components/pages/ExperimentsPage/ExperimentsPage.tsx b/apps/opik-frontend/src/components/pages/ExperimentsPage/ExperimentsPage.tsx index c1c5a58391..9a0d9bec05 100644 --- a/apps/opik-frontend/src/components/pages/ExperimentsPage/ExperimentsPage.tsx +++ b/apps/opik-frontend/src/components/pages/ExperimentsPage/ExperimentsPage.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo, useRef, useState } from "react"; -import { Info } from "lucide-react"; +import { Info, RotateCw } from "lucide-react"; import useLocalStorageState from "use-local-storage-state"; import { ColumnPinningState, @@ -7,6 +7,12 @@ import { RowSelectionState, } from "@tanstack/react-table"; import { keepPreviousData } from "@tanstack/react-query"; +import { + JsonParam, + NumberParam, + StringParam, + useQueryParam, +} from "use-query-params"; import get from "lodash/get"; import DataTable from "@/components/shared/DataTable/DataTable"; @@ -34,6 +40,7 @@ import ExperimentsFiltersButton from "@/components/pages/ExperimentsShared/Exper import ExperimentRowActionsCell from "@/components/pages/ExperimentsPage/ExperimentRowActionsCell"; import ExperimentsChartsWrapper from "@/components/pages/ExperimentsPage/charts/ExperimentsChartsWrapper"; import SearchInput from "@/components/shared/SearchInput/SearchInput"; +import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import useGroupedExperimentsList, { @@ -112,18 +119,34 @@ const ExperimentsPage: React.FunctionComponent = () => { const resetDialogKeyRef = useRef(0); const [openDialog, setOpenDialog] = useState(false); - const [search, setSearch] = useState(""); - const [page, setPage] = useState(1); - const [datasetId, setDatasetId] = useState(""); + const [search = "", setSearch] = useQueryParam("search", StringParam, { + updateType: "replaceIn", + }); + + const [page = 1, setPage] = useQueryParam("page", NumberParam, { + updateType: "replaceIn", + }); + + const [datasetId = "", setDatasetId] = useQueryParam("dataset", StringParam, { + updateType: "replaceIn", + }); + + const [groupLimit, setGroupLimit] = useQueryParam>( + "limits", + { ...JsonParam, default: {} }, + { + updateType: "replaceIn", + }, + ); + const [rowSelection, setRowSelection] = useState({}); - const [groupLimit, setGroupLimit] = useState>({}); - const { data, isPending } = useGroupedExperimentsList({ + const { data, isPending, refetch } = useGroupedExperimentsList({ workspaceName, groupLimit, - datasetId, - search, - page, + datasetId: datasetId!, + search: search!, + page: page!, size: DEFAULT_GROUPS_PER_PAGE, polling: true, }); @@ -297,19 +320,29 @@ const ExperimentsPage: React.FunctionComponent = () => {
+ + + { />
Promise; }; const extractPageSize = ( @@ -91,7 +91,10 @@ export default function useGroupedExperimentsList( ); const isFilteredByDataset = Boolean(params.datasetId); - const { data: deletedDatasetExperiments } = useExperimentsList( + const { + data: deletedDatasetExperiments, + refetch: refetchDeletedDatasetExperiments, + } = useExperimentsList( { workspaceName: params.workspaceName, search: params.search, @@ -106,7 +109,11 @@ export default function useGroupedExperimentsList( }, ); - const { data: dataset, isPending: isDatasetPending } = useDatasetById( + const { + data: dataset, + isPending: isDatasetPending, + refetch: refetchDataset, + } = useDatasetById( { datasetId: params.datasetId!, }, @@ -116,22 +123,25 @@ export default function useGroupedExperimentsList( const hasRemovedDatasetExperiments = (deletedDatasetExperiments?.total || 0) > 0; - const { data: datasetsRowData, isPending: isDatasetsPending } = - useDatasetsList( - { - workspaceName: params.workspaceName, - page: params.page, - size: params.size, - withExperimentsOnly: true, - sorting: GROUP_SORTING, - promptId: params.promptId, - }, - { - placeholderData: keepPreviousData, - refetchInterval, - enabled: !isFilteredByDataset, - } as never, - ); + const { + data: datasetsRowData, + isPending: isDatasetsPending, + refetch: refetchDatasetsRowData, + } = useDatasetsList( + { + workspaceName: params.workspaceName, + page: params.page, + size: params.size, + withExperimentsOnly: true, + sorting: GROUP_SORTING, + promptId: params.promptId, + }, + { + placeholderData: keepPreviousData, + refetchInterval, + enabled: !isFilteredByDataset, + } as never, + ); const datasetsData = useMemo(() => { return ( @@ -264,6 +274,23 @@ export default function useGroupedExperimentsList( total, ]); + const refetch = useCallback( + (options: RefetchOptions) => { + return Promise.all([ + refetchDeletedDatasetExperiments(options), + refetchDataset(options), + refetchDatasetsRowData(options), + ...experimentsResponse.map((r) => r.refetch(options)), + ]); + }, + [ + experimentsResponse, + refetchDataset, + refetchDatasetsRowData, + refetchDeletedDatasetExperiments, + ], + ); + const isPending = (isFilteredByDataset ? isDatasetPending : isDatasetsPending) || (experimentsResponse.length > 0 && @@ -273,5 +300,6 @@ export default function useGroupedExperimentsList( return { data, isPending, + refetch, } as UseGroupedExperimentsListResponse; }