Skip to content

Commit

Permalink
[OPIK-350] [Prompts Library][FE] Prompts details: Experiments tab (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
andriidudar authored Nov 13, 2024
1 parent 20b9e11 commit f53a671
Show file tree
Hide file tree
Showing 16 changed files with 449 additions and 130 deletions.
3 changes: 3 additions & 0 deletions apps/opik-frontend/src/api/datasets/useDatasetsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Dataset } from "@/types/datasets";
type UseDatasetsListParams = {
workspaceName: string;
withExperimentsOnly?: boolean;
promptId?: string;
search?: string;
page: number;
size: number;
Expand All @@ -21,6 +22,7 @@ const getDatasetsList = async (
{
workspaceName,
withExperimentsOnly,
promptId,
search,
size,
page,
Expand All @@ -34,6 +36,7 @@ const getDatasetsList = async (
with_experiments_only: withExperimentsOnly,
}),
...(search && { name: search }),
...(promptId && { prompt_id: promptId }),
size,
page,
},
Expand Down
3 changes: 3 additions & 0 deletions apps/opik-frontend/src/api/datasets/useExperimentsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Experiment } from "@/types/datasets";
export type UseExperimentsListParams = {
workspaceName: string;
datasetId?: string;
promptId?: string;
datasetDeleted?: boolean;
search?: string;
page: number;
Expand All @@ -22,6 +23,7 @@ export const getExperimentsList = async (
{
workspaceName,
datasetId,
promptId,
datasetDeleted,
search,
size,
Expand All @@ -35,6 +37,7 @@ export const getExperimentsList = async (
...(isBoolean(datasetDeleted) && { dataset_deleted: datasetDeleted }),
...(search && { name: search }),
...(datasetId && { datasetId }),
...(promptId && { prompt_id: promptId }),
size,
page,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import React, { useCallback, useMemo, useRef, useState } from "react";
import { Info } from "lucide-react";
import { useNavigate } from "@tanstack/react-router";
import useLocalStorageState from "use-local-storage-state";
import {
ExpandedState,
GroupingState,
RowSelectionState,
Row,
} from "@tanstack/react-table";
import { RowSelectionState } from "@tanstack/react-table";

import DataTable from "@/components/shared/DataTable/DataTable";
import DataTablePagination from "@/components/shared/DataTablePagination/DataTablePagination";
Expand All @@ -29,32 +18,32 @@ import { COLUMN_TYPE, ColumnData } from "@/types/shared";
import { convertColumnDataToColumn } from "@/lib/table";
import ColumnsButton from "@/components/shared/ColumnsButton/ColumnsButton";
import AddExperimentDialog from "@/components/pages/ExperimentsPage/AddExperimentDialog";
import ExperimentsActionsPanel from "@/components/pages/ExperimentsPage/ExperimentsActionsPanel";
import ExperimentsFiltersButton from "@/components/pages/ExperimentsPage/ExperimentsFiltersButton";
import ExperimentsActionsPanel from "@/components/pages/ExperimentsShared/ExperimentsActionsPanel";
import ExperimentsFiltersButton from "@/components/pages/ExperimentsShared/ExperimentsFiltersButton";
import ExperimentRowActionsCell from "@/components/pages/ExperimentsPage/ExperimentRowActionsCell";
import ExperimentsChartsWrapper from "@/components/pages/ExperimentsPage/charts/ExperimentsChartsWrapper";
import SearchInput from "@/components/shared/SearchInput/SearchInput";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import useGroupedExperimentsList, {
checkIsMoreRowId,
DEFAULT_EXPERIMENTS_PER_GROUP,
GroupedExperiment,
GROUPING_COLUMN,
} from "@/hooks/useGroupedExperimentsList";
import {
generateExperimentNameColumDef,
generateGroupedCellDef,
} from "@/components/pages/ExperimentsPage/table";
getIsMoreRow,
getRowId,
GROUPING_CONFIG,
} from "@/components/pages/ExperimentsShared/table";
import { useExpandingConfig } from "@/components/pages/ExperimentsShared/useExpandingConfig";
import { useGroupLimitsConfig } from "@/components/pages/ExperimentsShared/useGroupLimitsConfig";

const SELECTED_COLUMNS_KEY = "experiments-selected-columns";
const COLUMNS_WIDTH_KEY = "experiments-columns-width";
const COLUMNS_ORDER_KEY = "experiments-columns-order";

const getRowId = (e: GroupedExperiment) => e.id;
const getIsMoreRow = (row: Row<GroupedExperiment>) =>
checkIsMoreRowId(row?.original?.id || "");

export const DEFAULT_COLUMNS: ColumnData<GroupedExperiment>[] = [
{
id: "id",
Expand Down Expand Up @@ -89,8 +78,6 @@ export const DEFAULT_SELECTED_COLUMNS: string[] = [
const ExperimentsPage: React.FunctionComponent = () => {
const navigate = useNavigate();
const workspaceName = useAppStore((state) => state.activeWorkspaceName);

const openGroupsRef = useRef<Record<string, boolean>>({});
const resetDialogKeyRef = useRef(0);
const [openDialog, setOpenDialog] = useState<boolean>(false);

Expand All @@ -99,8 +86,7 @@ const ExperimentsPage: React.FunctionComponent = () => {
const [size, setSize] = useState(5);
const [datasetId, setDatasetId] = useState("");
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [expanded, setExpanded] = useState<ExpandedState>({});
const [groupLimit, setGroupLimit] = useState<Record<string, number>>({});
const { groupLimit, renderMoreRow } = useGroupLimitsConfig();

const { data, isPending } = useGroupedExperimentsList({
workspaceName,
Expand Down Expand Up @@ -147,7 +133,9 @@ const ExperimentsPage: React.FunctionComponent = () => {

const columns = useMemo(() => {
return [
generateExperimentNameColumDef<GroupedExperiment>(),
generateExperimentNameColumDef<GroupedExperiment>({
size: columnsWidth["name"],
}),
generateGroupedCellDef<GroupedExperiment, unknown>({
id: GROUPING_COLUMN,
label: "Dataset",
Expand Down Expand Up @@ -178,27 +166,6 @@ const ExperimentsPage: React.FunctionComponent = () => {
];
}, [selectedColumns, columnsWidth, columnsOrder]);

useEffect(() => {
const updateForExpandedState: Record<string, boolean> = {};
groupIds.forEach((groupId) => {
const id = `${GROUPING_COLUMN}:${groupId}`;
if (!openGroupsRef.current[id]) {
openGroupsRef.current[id] = true;
updateForExpandedState[id] = true;
}
});

if (Object.keys(updateForExpandedState).length) {
setExpanded((state) => {
if (state === true) return state;
return {
...state,
...updateForExpandedState,
};
});
}
}, [groupIds]);

const resizeConfig = useMemo(
() => ({
enabled: true,
Expand All @@ -207,22 +174,9 @@ const ExperimentsPage: React.FunctionComponent = () => {
[setColumnsWidth],
);

const groupingConfig = useMemo(
() => ({
groupedColumnMode: false as const,
grouping: [GROUPING_COLUMN] as GroupingState,
}),
[],
);

const expandingConfig = useMemo(
() => ({
autoResetExpanded: false,
expanded,
setExpanded,
}),
[expanded, setExpanded],
);
const expandingConfig = useExpandingConfig({
groupIds,
});

const handleNewExperimentClick = useCallback(() => {
setOpenDialog(true);
Expand All @@ -245,32 +199,6 @@ const ExperimentsPage: React.FunctionComponent = () => {
[navigate, workspaceName],
);

const renderMoreRow = useCallback((row: Row<GroupedExperiment>) => {
return (
<tr key={row.id} className="border-b">
<td colSpan={row.getAllCells().length} className="px-2 py-1">
<Button
variant="link"
className="w-full"
onClick={() => {
setGroupLimit((state) => {
return {
...state,
[row.original.dataset_id]:
(state[row.original.dataset_id] ||
DEFAULT_EXPERIMENTS_PER_GROUP) +
DEFAULT_EXPERIMENTS_PER_GROUP,
};
});
}}
>
Load {DEFAULT_EXPERIMENTS_PER_GROUP} more experiments
</Button>
</td>
</tr>
);
}, []);

if (isPending) {
return <Loader />;
}
Expand Down Expand Up @@ -322,7 +250,7 @@ const ExperimentsPage: React.FunctionComponent = () => {
setRowSelection,
}}
expandingConfig={expandingConfig}
groupingConfig={groupingConfig}
groupingConfig={GROUPING_CONFIG}
getRowId={getRowId}
noData={
<DataTableNoData title={noDataText}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button";
import { Experiment } from "@/types/datasets";
import { useNavigate } from "@tanstack/react-router";
import useAppStore from "@/store/AppStore";
import FilterExperimentsToCompareDialog from "@/components/pages/ExperimentsPage/FilterExperimentsToCompareDialog";
import FilterExperimentsToCompareDialog from "@/components/pages/ExperimentsShared/FilterExperimentsToCompareDialog";
import useExperimentBatchDeleteMutation from "@/api/datasets/useExperimentBatchDeleteMutation";
import ConfirmDialog from "@/components/shared/ConfirmDialog/ConfirmDialog";
import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
import { Checkbox } from "@/components/ui/checkbox";
import React from "react";
import { CellContext, ColumnDef, flexRender } from "@tanstack/react-table";
import { Checkbox } from "@/components/ui/checkbox";
import {
CellContext,
ColumnDef,
flexRender,
GroupingState,
Row,
} from "@tanstack/react-table";
import { ColumnData } from "@/types/shared";
import { Button } from "@/components/ui/button";
import { ChevronDown, ChevronUp, Text } from "lucide-react";
import { mapColumnDataFields } from "@/lib/table";
import { cn } from "@/lib/utils";
import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
import {
checkIsMoreRowId,
GroupedExperiment,
GROUPING_COLUMN,
} from "@/hooks/useGroupedExperimentsList";
import ResourceLink, {
RESOURCE_TYPE,
} from "@/components/shared/ResourceLink/ResourceLink";

export const GROUPING_CONFIG = {
groupedColumnMode: false as const,
grouping: [GROUPING_COLUMN] as GroupingState,
};

export const getRowId = (e: GroupedExperiment) => e.id;
export const getIsMoreRow = (row: Row<GroupedExperiment>) =>
checkIsMoreRowId(row?.original?.id || "");

export const generateExperimentNameColumDef = <TData,>() => {
export const generateExperimentNameColumDef = <TData,>({
size,
asResource = false,
}: {
size?: number;
asResource?: boolean;
}) => {
return {
accessorKey: "name",
header: ({ table }) => (
Expand All @@ -28,25 +57,43 @@ export const generateExperimentNameColumDef = <TData,>() => {
<span className="truncate">Name</span>
</div>
),
cell: (context) => (
<CellWrapper
metadata={context.column.columnDef.meta}
tableMetadata={context.table.options.meta}
>
<Checkbox
style={{
marginLeft: `${context.row.depth * 28}px`,
}}
onClick={(event) => event.stopPropagation()}
checked={context.row.getIsSelected()}
disabled={!context.row.getCanSelect()}
onCheckedChange={(value) => context.row.toggleSelected(!!value)}
aria-label="Select row"
/>
<span className="ml-6 truncate">{context.getValue() as string}</span>
</CellWrapper>
),
size: 180,
cell: (context) => {
const data = context.row.original as GroupedExperiment;
return (
<CellWrapper
metadata={context.column.columnDef.meta}
tableMetadata={context.table.options.meta}
>
<Checkbox
style={{
marginLeft: `${context.row.depth * 28}px`,
}}
onClick={(event) => event.stopPropagation()}
checked={context.row.getIsSelected()}
disabled={!context.row.getCanSelect()}
onCheckedChange={(value) => context.row.toggleSelected(!!value)}
aria-label="Select row"
/>
{asResource ? (
<div className="ml-6 min-w-1 max-w-full">
<ResourceLink
id={data.dataset_id}
name={data.name}
resource={RESOURCE_TYPE.experiment}
search={{
experiments: [data.id],
}}
/>
</div>
) : (
<span className="ml-6 truncate">
{context.getValue() as string}
</span>
)}
</CellWrapper>
);
},
size: size ?? 180,
minSize: 100,
enableSorting: false,
enableHiding: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { ExpandedState } from "@tanstack/react-table";
import { GROUPING_COLUMN } from "@/hooks/useGroupedExperimentsList";

export type UseExpandingConfigProps = {
groupIds: string[];
};

export const useExpandingConfig = ({ groupIds }: UseExpandingConfigProps) => {
const openGroupsRef = useRef<Record<string, boolean>>({});
const [expanded, setExpanded] = useState<ExpandedState>({});

useEffect(() => {
const updateForExpandedState: Record<string, boolean> = {};
groupIds.forEach((groupId) => {
const id = `${GROUPING_COLUMN}:${groupId}`;
if (!openGroupsRef.current[id]) {
openGroupsRef.current[id] = true;
updateForExpandedState[id] = true;
}
});

if (Object.keys(updateForExpandedState).length) {
setExpanded((state) => {
if (state === true) return state;
return {
...state,
...updateForExpandedState,
};
});
}
}, [groupIds]);

return useMemo(
() => ({
autoResetExpanded: false,
expanded,
setExpanded,
}),
[expanded, setExpanded],
);
};
Loading

0 comments on commit f53a671

Please sign in to comment.