feature: add command feature column to toolset table and other minor table improvements (#5343)
* refactor: Update toolset configuration display name and description This commit updates the display name and description of the toolset configuration in the custom component. The display name is changed to "Edit tools" and the description is modified to "Modify tool names and descriptions to help agents understand when to use each tool." This improves the clarity and usability of the toolset configuration. * refactor: Update table modal header description handling * refactor: Add EditMode.POPOVER option to table schema * refactor: Add EditMode.POPOVER option to table schema * refactor: Add table icon to table schema and components * add style for not editable cells * Add "commands" field to tool table schema * refactor: Add "no_blank" and "valid_csv" field parsers - Added "no_blank" field parser to remove leading and trailing whitespace from strings and throw an error if the string is blank. - Added "valid_csv" field parser to replace whitespace with commas in strings. * refactor: Add commands to tool description in ComponentToolkit * refactor: Improve parsing of commands in validCommands function * Update src/frontend/src/utils/stringManipulation.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * [autofix.ci] apply automated fixes * add support for hints on table header * update descriptions on tool table * [autofix.ci] apply automated fixes --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
33a792242d
commit
18acd304a7
14 changed files with 185 additions and 51 deletions
|
|
@ -209,3 +209,14 @@ code {
|
|||
resize: none !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.cell-disable-edit {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.cell-disable-edit.ag-cell-focus {
|
||||
outline: none !important;
|
||||
border: 0px !important;
|
||||
box-shadow: none !important;
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import ShadTooltip from "@/components/common/shadTooltipComponent";
|
||||
import TableModal from "@/modals/tableModal";
|
||||
import { FormatColumns, generateBackendColumnsFromValue } from "@/utils/utils";
|
||||
import { DataTypeDefinition, SelectionChangedEvent } from "ag-grid-community";
|
||||
|
|
@ -20,6 +21,7 @@ export default function TableNodeComponent({
|
|||
table_options,
|
||||
trigger_icon = "Table",
|
||||
trigger_text = "Open Table",
|
||||
table_icon,
|
||||
}: InputProps<any[], TableComponentType>): JSX.Element {
|
||||
const dataTypeDefinitions: {
|
||||
[cellDataType: string]: DataTypeDefinition<any>;
|
||||
|
|
@ -67,7 +69,26 @@ export default function TableNodeComponent({
|
|||
const componentColumns = columns
|
||||
? columns
|
||||
: generateBackendColumnsFromValue(value ?? [], table_options);
|
||||
const AgColumns = FormatColumns(componentColumns);
|
||||
let AgColumns = FormatColumns(componentColumns);
|
||||
// add info to each column
|
||||
AgColumns = AgColumns.map((col) => {
|
||||
if (col.context?.info) {
|
||||
return {
|
||||
...col,
|
||||
headerComponent: () => (
|
||||
<div className="flex items-center gap-1">
|
||||
<div>{col.headerName}</div>
|
||||
<ShadTooltip content={col.context?.info}>
|
||||
<div>
|
||||
<ForwardedIconComponent name="Info" className="h-4 w-4" />
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
}
|
||||
return col;
|
||||
});
|
||||
function setAllRows() {
|
||||
if (agGrid.current && !agGrid.current.api.isDestroyed()) {
|
||||
const rows: any = [];
|
||||
|
|
@ -107,7 +128,7 @@ export default function TableNodeComponent({
|
|||
.map((column) => {
|
||||
const isCustomEdit =
|
||||
column.formatter &&
|
||||
((column.formatter === "text" && column.edit_mode !== "inline") ||
|
||||
((column.formatter === "text" && column.edit_mode === "modal") ||
|
||||
column.formatter === "json");
|
||||
return {
|
||||
field: column.name,
|
||||
|
|
@ -128,6 +149,8 @@ export default function TableNodeComponent({
|
|||
>
|
||||
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
|
||||
<TableModal
|
||||
stopEditingWhenCellsLoseFocus={true}
|
||||
tableIcon={table_icon}
|
||||
tableOptions={table_options}
|
||||
dataTypeDefinitions={dataTypeDefinitions}
|
||||
autoSizeStrategy={{ type: "fitGridWidth", defaultMinWidth: 100 }}
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ export function ParameterRenderComponent({
|
|||
table_options={templateData?.table_options}
|
||||
trigger_icon={templateData?.trigger_icon}
|
||||
trigger_text={templateData?.trigger_text}
|
||||
table_icon={templateData?.table_icon}
|
||||
/>
|
||||
);
|
||||
case "slider":
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export type TableComponentType = {
|
|||
table_options?: TableOptionsTypeAPI;
|
||||
trigger_text?: string;
|
||||
trigger_icon?: string;
|
||||
table_icon?: string;
|
||||
};
|
||||
|
||||
export type FloatComponentType = {
|
||||
|
|
|
|||
|
|
@ -16,11 +16,19 @@ interface TableModalProps extends TableComponentProps {
|
|||
children: React.ReactNode;
|
||||
tableOptions?: TableOptionsTypeAPI;
|
||||
hideColumns?: boolean | string[];
|
||||
tableIcon?: string;
|
||||
}
|
||||
|
||||
const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
||||
(
|
||||
{ tableTitle, description, children, disabled, ...props }: TableModalProps,
|
||||
{
|
||||
tableTitle,
|
||||
description,
|
||||
children,
|
||||
disabled,
|
||||
tableIcon,
|
||||
...props
|
||||
}: TableModalProps,
|
||||
ref: ForwardedRef<AgGridReact>,
|
||||
) => {
|
||||
return (
|
||||
|
|
@ -37,9 +45,14 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
|
|||
disable={disabled}
|
||||
>
|
||||
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={description}>
|
||||
<BaseModal.Header
|
||||
description={props.tableOptions?.description ?? description}
|
||||
>
|
||||
<span className="pr-2">{tableTitle}</span>
|
||||
<ForwardedIconComponent name="Table" className="mr-2 h-4 w-4" />
|
||||
<ForwardedIconComponent
|
||||
name={tableIcon ?? "Table"}
|
||||
className="mr-2 h-4 w-4"
|
||||
/>
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<TableComponent
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ export type FieldParserType =
|
|||
| "pascal_case"
|
||||
| "kebab_case"
|
||||
| "lowercase"
|
||||
| "uppercase";
|
||||
| "uppercase"
|
||||
| "no_blank"
|
||||
| "valid_csv"
|
||||
| "commands";
|
||||
|
||||
export type TableOptionsTypeAPI = {
|
||||
block_add?: boolean;
|
||||
|
|
@ -316,4 +319,5 @@ export type TableOptionsTypeAPI = {
|
|||
FieldValidatorType | { [key: string]: FieldValidatorType }
|
||||
>;
|
||||
field_parsers?: Array<FieldParserType | { [key: string]: FieldParserType }>;
|
||||
description?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@ export interface ColumnField {
|
|||
description?: string;
|
||||
disable_edit?: boolean;
|
||||
default?: any; // Add this line
|
||||
edit_mode?: "modal" | "inline";
|
||||
edit_mode?: "modal" | "inline" | "popover";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,34 @@ function toUpperCase(str: string): string {
|
|||
return str.toUpperCase();
|
||||
}
|
||||
|
||||
function noBlank(str: string): string {
|
||||
const trim = str.trim();
|
||||
if (trim === "") {
|
||||
throw new Error("String is blank");
|
||||
}
|
||||
return trim;
|
||||
}
|
||||
|
||||
function validCsv(str: string): string {
|
||||
return str.trim().replace(/\s+/g, ",");
|
||||
}
|
||||
|
||||
function validCommands(str: string): string {
|
||||
return str
|
||||
.trim()
|
||||
.split(/[\s,]+/)
|
||||
.flatMap((cmd) => {
|
||||
cmd = cmd.trim();
|
||||
cmd = cmd.replace(/\\/g, "/");
|
||||
return cmd
|
||||
.split("/")
|
||||
.filter((part) => part.length > 0)
|
||||
.map((part) => `/${part}`);
|
||||
})
|
||||
.filter((cmd) => cmd.length > 1)
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
export function parseString(
|
||||
str: string,
|
||||
parsers: FieldParserType[] | FieldParserType,
|
||||
|
|
@ -48,25 +76,38 @@ export function parseString(
|
|||
}
|
||||
|
||||
for (const parser of parsersArray) {
|
||||
switch (parser) {
|
||||
case "snake_case":
|
||||
result = toSnakeCase(result);
|
||||
break;
|
||||
case "camel_case":
|
||||
result = toCamelCase(result);
|
||||
break;
|
||||
case "pascal_case":
|
||||
result = toPascalCase(result);
|
||||
break;
|
||||
case "kebab_case":
|
||||
result = toKebabCase(result);
|
||||
break;
|
||||
case "lowercase":
|
||||
result = toLowerCase(result);
|
||||
break;
|
||||
case "uppercase":
|
||||
result = toUpperCase(result);
|
||||
break;
|
||||
try {
|
||||
switch (parser) {
|
||||
case "snake_case":
|
||||
result = toSnakeCase(result);
|
||||
break;
|
||||
case "camel_case":
|
||||
result = toCamelCase(result);
|
||||
break;
|
||||
case "pascal_case":
|
||||
result = toPascalCase(result);
|
||||
break;
|
||||
case "kebab_case":
|
||||
result = toKebabCase(result);
|
||||
break;
|
||||
case "lowercase":
|
||||
result = toLowerCase(result);
|
||||
break;
|
||||
case "uppercase":
|
||||
result = toUpperCase(result);
|
||||
break;
|
||||
case "no_blank":
|
||||
result = noBlank(result);
|
||||
break;
|
||||
case "valid_csv":
|
||||
result = validCsv(result);
|
||||
break;
|
||||
case "commands":
|
||||
result = validCommands(result);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error in parser ${parser}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import TableAutoCellRender from "@/components/core/parameterRenderComponent/components/tableComponent/components/tableAutoCellRender";
|
||||
import useAlertStore from "@/stores/alertStore";
|
||||
import { ColumnField, FormatterType } from "@/types/utils/functions";
|
||||
import { ColDef, ColGroupDef, ValueParserParams } from "ag-grid-community";
|
||||
import clsx, { ClassValue } from "clsx";
|
||||
|
|
@ -526,17 +527,26 @@ export function FormatColumns(columns: ColumnField[]): ColDef<any>[] {
|
|||
field: col.name,
|
||||
sortable: col.sortable,
|
||||
filter: col.filterable,
|
||||
editable: !col.disable_edit,
|
||||
context: col.description ? { info: col.description } : {},
|
||||
cellClass: col.disable_edit ? "cell-disable-edit" : "",
|
||||
valueParser: (params: ValueParserParams) => {
|
||||
const { context, newValue, colDef } = params;
|
||||
const { context, newValue, colDef, oldValue } = params;
|
||||
if (
|
||||
context.field_parsers &&
|
||||
context.field_parsers[colDef.field ?? ""]
|
||||
) {
|
||||
return parseString(
|
||||
newValue,
|
||||
context.field_parsers[colDef.field ?? ""],
|
||||
);
|
||||
try {
|
||||
return parseString(
|
||||
newValue,
|
||||
context.field_parsers[colDef.field ?? ""],
|
||||
);
|
||||
} catch (error: any) {
|
||||
useAlertStore.getState().setErrorData({
|
||||
title: "Error parsing string",
|
||||
list: [String(error.message ?? error)],
|
||||
});
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
return newValue;
|
||||
},
|
||||
|
|
@ -551,15 +561,17 @@ export function FormatColumns(columns: ColumnField[]): ColDef<any>[] {
|
|||
formatter: col.formatter,
|
||||
};
|
||||
if (col.formatter !== FormatterType.text || col.edit_mode !== "inline") {
|
||||
newCol.cellRenderer = TableAutoCellRender;
|
||||
} else {
|
||||
newCol.wrapText = true;
|
||||
newCol.autoHeight = true;
|
||||
newCol.cellEditor = "agLargeTextCellEditor";
|
||||
newCol.cellEditorPopup = true;
|
||||
newCol.cellEditorParams = {
|
||||
maxLength: 100000000,
|
||||
};
|
||||
if (col.edit_mode === "popover") {
|
||||
newCol.wrapText = true;
|
||||
newCol.autoHeight = true;
|
||||
newCol.cellEditor = "agLargeTextCellEditor";
|
||||
newCol.cellEditorPopup = true;
|
||||
newCol.cellEditorParams = {
|
||||
maxLength: 100000000,
|
||||
};
|
||||
} else {
|
||||
newCol.cellRenderer = TableAutoCellRender;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newCol;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue