diff --git a/agenta-web/src/components/NLines/NLines.tsx b/agenta-web/src/components/NLines/NLines.tsx new file mode 100644 index 0000000000..a48fd4c780 --- /dev/null +++ b/agenta-web/src/components/NLines/NLines.tsx @@ -0,0 +1,54 @@ +import {Space, Typography} from "antd" +import React, {useMemo, useState} from "react" +import {createUseStyles} from "react-jss" + +const useStyles = createUseStyles({ + text: ({lines}: {lines: number}) => ({ + display: "-webkit-box", + "-webkit-line-clamp": lines, + "-webkit-box-orient": "vertical", + }), +}) + +interface Props { + lines?: number + allowReadMore?: boolean + children: React.ReactNode +} + +const NLines: React.FC = ({lines = 8, allowReadMore = false, children}) => { + const [collapsed, setCollapsed] = useState(true) + const classes = useStyles({lines}) + const [ref, setRef] = useState() + + const actualLines = useMemo(() => { + if (ref) { + const lineHeight = parseInt(getComputedStyle(ref).lineHeight) + return ref.offsetHeight / lineHeight + } + return lines + }, [collapsed, ref]) + + return ( + + setRef(elem!)} + className={`overflow-hidden text-ellipsis ${collapsed ? classes.text : ""}`} + > + {children} + + {allowReadMore && actualLines >= lines && ( + { + setCollapsed(!collapsed) + e.stopPropagation() + }} + > + {collapsed ? "Read more" : "Read less"} + + )} + + ) +} + +export default NLines diff --git a/agenta-web/src/components/Playground/Views/GroupedSelect.tsx b/agenta-web/src/components/Playground/Views/GroupedSelect.tsx index 42944bbf6b..5ec7a51061 100644 --- a/agenta-web/src/components/Playground/Views/GroupedSelect.tsx +++ b/agenta-web/src/components/Playground/Views/GroupedSelect.tsx @@ -62,6 +62,17 @@ const getTextContent = (element: React.ReactNode): string => { const filterOption = (input: string, option?: {label: React.ReactNode; value: string}) => getTextContent(option?.label).toLowerCase().includes(input.toLowerCase()) +export const ModelName: React.FC<{label: string; key: string}> = ({label, key}) => { + const classes = useStyles() + + return ( +
+ {iconMap[key] ? React.createElement(iconMap[key]) : null} + {label} +
+ ) +} + export const GroupedSelect: React.FC = ({ choices, defaultValue, @@ -70,19 +81,9 @@ export const GroupedSelect: React.FC = ({ const classes = useStyles() const options = Object.entries(choices).map(([groupLabel, groupChoices]) => ({ - label: ( -
- {iconMap[groupLabel] ? React.createElement(iconMap[groupLabel]) : null} - {groupLabel} -
- ), + label: , options: groupChoices.map((choice) => ({ - label: ( -
- {iconMap[groupLabel] ? React.createElement(iconMap[groupLabel]) : null} - {choice} -
- ), + label: , value: choice, })), })) diff --git a/agenta-web/src/components/ServerTable/components.tsx b/agenta-web/src/components/ServerTable/components.tsx index de3d5bd30d..a1e5454f2c 100644 --- a/agenta-web/src/components/ServerTable/components.tsx +++ b/agenta-web/src/components/ServerTable/components.tsx @@ -1,9 +1,9 @@ import {GenericObject, JSSTheme, PaginationQuery} from "@/lib/Types" -import {Button, Dropdown, Input, Space} from "antd" +import {Button, Dropdown, DropdownProps, Input, Space} from "antd" import {ColumnsType} from "antd/es/table" import {FilterDropdownProps} from "antd/es/table/interface" import dayjs from "dayjs" -import React, {ReactNode, useMemo} from "react" +import React, {ReactNode, useMemo, useState} from "react" import {createUseStyles} from "react-jss" import {Resizable} from "react-resizable" import EnforceAntdStyles from "../EnforceAntdStyles/EnforceAntdStyles" @@ -100,6 +100,13 @@ interface ColsDropdownProps { export const ColsDropdown = ({columns, hiddenCols, setHiddenCols}: ColsDropdownProps) => { const classes = useStyles() + const [isFilterColsDropdownOpen, setIsFilterColsDropdownOpen] = useState(false) + + const handleOpenChangeFilterCols: DropdownProps["onOpenChange"] = (nextOpen, info) => { + if (info.source === "trigger" || nextOpen) { + setIsFilterColsDropdownOpen(nextOpen) + } + } const shownCols = useMemo( () => columns @@ -119,6 +126,8 @@ export const ColsDropdown = ({columns, hiddenCols, setHiddenCols}: ColsDropd return ( ({ @@ -130,7 +139,10 @@ export const ColsDropdown = ({columns, hiddenCols, setHiddenCols}: ColsDropd ), })) as any, - onClick: ({key}) => onColToggle(key), + onClick: ({key}) => { + onColToggle(key) + setIsFilterColsDropdownOpen(true) + }, className: classes.dropdownMenu, }} > diff --git a/agenta-web/src/components/ServerTable/index.tsx b/agenta-web/src/components/ServerTable/index.tsx index 628472f71a..061558ece4 100644 --- a/agenta-web/src/components/ServerTable/index.tsx +++ b/agenta-web/src/components/ServerTable/index.tsx @@ -65,7 +65,7 @@ const ServerTable = ( "tableParams", props.defaultTableParams && JSON.stringify(props.defaultTableParams), ) - const [_hiddenCols, _setHiddenCols] = useQueryParam("hiddenCols", "") + const [_hiddenCols, _setHiddenCols] = useQueryParam("hiddenCols") const [data, setData] = useState([]) const [loading, setLoading] = useState(false) @@ -78,6 +78,10 @@ const ServerTable = ( setColumns( (props.columns || []).map((item) => ({...item, width: item.width})) as DataCol[], ) + setHiddenCols([ + ...hiddenCols, + ...props.columns.filter((col) => col.hidden).map((col) => col.key as string), + ]) }, [props.columns]) useEffect(() => { diff --git a/agenta-web/src/lib/helpers/fileManipulations.ts b/agenta-web/src/lib/helpers/fileManipulations.ts index d4434e6200..e3b6890e92 100644 --- a/agenta-web/src/lib/helpers/fileManipulations.ts +++ b/agenta-web/src/lib/helpers/fileManipulations.ts @@ -5,6 +5,8 @@ export const convertToCsv = (rows: GenericObject[], header: string[]) => { return Papa.unparse({fields: header.filter((item) => !!item), data: rows}) } +export const escapeNewlines = (value: string) => value.replace(/\n/g, "\\n") + export const downloadCsv = (csvContent: string, filename: string): void => { if (typeof window === "undefined") return diff --git a/agenta-web/src/lib/helpers/variantHelper.ts b/agenta-web/src/lib/helpers/variantHelper.ts index ff3e36109d..dcfdc205e0 100644 --- a/agenta-web/src/lib/helpers/variantHelper.ts +++ b/agenta-web/src/lib/helpers/variantHelper.ts @@ -85,7 +85,7 @@ export const variantNameWithRev = (variant: { }) => { let name = variant.variant_name if (![undefined, null].includes(variant.revision as any)) { - name += `v${variant.revision}` + name += ` v${variant.revision}` } return name }