support oneof for array type
This commit is contained in:
1 parent
826b69a587
commit
de9c9a48c9
6 files changed
+175
-117
No files matched your search
@@ -121,7 +121,7 @@
|
|||||||
"node.name": "Node name",
|
"node.name": "Node name",
|
||||||
"node.noNodeSelected": "No node selected",
|
"node.noNodeSelected": "No node selected",
|
||||||
"node.notFound": "Node '{{name}}' not found",
|
"node.notFound": "Node '{{name}}' not found",
|
||||||
"node.oneof.error": "Only one is allowed between input '{{input}}' and argument '{{arg}}({{desc}})'",
|
"node.oneof.error": "Only one is allowed between input '{{input}}' and argument '{{desc}}({{arg}})'",
|
||||||
"node.oneof.inputNotfound": "Input '{{input}}' not found",
|
"node.oneof.inputNotfound": "Input '{{input}}' not found",
|
||||||
"node.outputVariable": "Output variables",
|
"node.outputVariable": "Output variables",
|
||||||
"node.pasteDataError": "Paste data error",
|
"node.pasteDataError": "Paste data error",
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
"node.name": "节点名称",
|
"node.name": "节点名称",
|
||||||
"node.noNodeSelected": "未选择任务节点",
|
"node.noNodeSelected": "未选择任务节点",
|
||||||
"node.notFound": "节点 “{{name}}” 不存在",
|
"node.notFound": "节点 “{{name}}” 不存在",
|
||||||
"node.oneof.error": "输入项 “{{input}}” 和参数 “{{arg}}({{desc}})” 之中,只能选择设置其中之一",
|
"node.oneof.error": "输入项 “{{input}}” 和参数 “{{desc}}({{arg}})” 之中,只能选择设置其中之一",
|
||||||
"node.oneof.inputNotfound": "输入项“{{input}}”不存在",
|
"node.oneof.inputNotfound": "输入项“{{input}}”不存在",
|
||||||
"node.outputVariable": "输出变量",
|
"node.outputVariable": "输出变量",
|
||||||
"node.pasteDataError": "粘贴数据出错",
|
"node.pasteDataError": "粘贴数据出错",
|
||||||
|
|||||||
@@ -416,5 +416,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"desc": "等待"
|
"desc": "等待"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TestOneof",
|
||||||
|
"desc": "测试oneof",
|
||||||
|
"type": "Action",
|
||||||
|
"input": ["选项?"],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "option",
|
||||||
|
"desc": "选项",
|
||||||
|
"type": "int[]?",
|
||||||
|
"oneof": "选项"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -104,6 +104,15 @@
|
|||||||
"args": {
|
"args": {
|
||||||
"builtin": "afterRunFailure"
|
"builtin": "afterRunFailure"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "13",
|
||||||
|
"name": "TestOneof",
|
||||||
|
"input": [
|
||||||
|
"context"
|
||||||
|
],
|
||||||
|
"output": [],
|
||||||
|
"args": {}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+143
-113
@@ -760,7 +760,7 @@ const NodeInspector: FC = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
data.args[arg.name] = arr;
|
data.args[arg.name] = !isNodeArgOptional(arg) ? arr : arr.length ? arr : undefined;
|
||||||
} else if (isJsonType(type)) {
|
} else if (isJsonType(type)) {
|
||||||
try {
|
try {
|
||||||
data.args[arg.name] = value === "null" ? null : JSON.parse(value);
|
data.args[arg.name] = value === "null" ? null : JSON.parse(value);
|
||||||
@@ -1070,7 +1070,7 @@ const NodeInspector: FC = () => {
|
|||||||
setFieldValue(`input.${i}`, value);
|
setFieldValue(`input.${i}`, value);
|
||||||
validateFields([argName]);
|
validateFields([argName]);
|
||||||
}
|
}
|
||||||
if (!checkOneof(getFieldValue(argName) ?? "", value)) {
|
if (!checkOneof(arg, getFieldValue(argName), value)) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
t("node.oneof.error", {
|
t("node.oneof.error", {
|
||||||
@@ -1116,118 +1116,148 @@ const NodeInspector: FC = () => {
|
|||||||
const type = getNodeArgRawType(arg);
|
const type = getNodeArgRawType(arg);
|
||||||
if (isNodeArgArray(arg)) {
|
if (isNodeArgArray(arg)) {
|
||||||
return (
|
return (
|
||||||
<Form.Item key={`args.${arg.name}`}>
|
<Form.List
|
||||||
<Form.List name={`args.${arg.name}`}>
|
key={`args.${arg.name}`}
|
||||||
{(items, { add, remove }, { errors }) => (
|
name={`args.${arg.name}`}
|
||||||
<div style={{ display: "flex", rowGap: 0, flexDirection: "column" }}>
|
rules={[
|
||||||
{items.map((item, idx) => (
|
{
|
||||||
<Flex key={item.key} gap={4}>
|
validator(_, value: unknown[]) {
|
||||||
<Form.Item
|
if (!arg.oneof) {
|
||||||
name={item.name}
|
return Promise.resolve();
|
||||||
label={idx === 0 ? `${arg.desc}[${idx}]` : `[${idx}]`}
|
}
|
||||||
validateTrigger={["onChange", "onBlur"]}
|
const idx = def.input?.findIndex(
|
||||||
style={{ width: "100%", marginBottom: 5 }}
|
(input) => input.replace("?", "") === arg.oneof
|
||||||
initialValue={
|
);
|
||||||
isBoolType(type) ? arg.default ?? false : arg.default
|
if (idx === undefined || idx < 0) {
|
||||||
}
|
return Promise.reject(
|
||||||
valuePropName={isBoolType(type) ? "checked" : undefined}
|
new Error(t("node.oneof.inputNotfound", { input: arg.oneof }))
|
||||||
rules={[
|
);
|
||||||
{
|
}
|
||||||
required,
|
const inputName = `input.${idx}`;
|
||||||
message: t("fieldRequired", { field: arg.desc }),
|
if (!form.isFieldValidating(inputName)) {
|
||||||
|
form.setFieldValue(`args.${arg.name}`, value);
|
||||||
|
form.validateFields([inputName]);
|
||||||
|
}
|
||||||
|
if (!checkOneof(arg, value, form.getFieldValue(inputName))) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
t("node.oneof.error", {
|
||||||
|
input: def.input![idx],
|
||||||
|
arg: arg.name,
|
||||||
|
desc: arg.desc ?? "",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{(items, { add, remove }, { errors }) => (
|
||||||
|
<div style={{ display: "flex", rowGap: 0, flexDirection: "column" }}>
|
||||||
|
{items.map((item, idx) => (
|
||||||
|
<Flex key={item.key} gap={4}>
|
||||||
|
<Form.Item
|
||||||
|
name={item.name}
|
||||||
|
label={idx === 0 ? `${arg.desc}[${idx}]` : `[${idx}]`}
|
||||||
|
validateTrigger={["onChange", "onBlur"]}
|
||||||
|
style={{ width: "100%", marginBottom: 5 }}
|
||||||
|
initialValue={isBoolType(type) ? arg.default ?? false : arg.default}
|
||||||
|
valuePropName={isBoolType(type) ? "checked" : undefined}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required,
|
||||||
|
message: t("fieldRequired", { field: arg.desc }),
|
||||||
|
},
|
||||||
|
() => ({
|
||||||
|
validator(_, value) {
|
||||||
|
return validateArg(
|
||||||
|
editingNode.data,
|
||||||
|
arg,
|
||||||
|
value,
|
||||||
|
workspace.usingVars
|
||||||
|
);
|
||||||
},
|
},
|
||||||
() => ({
|
}),
|
||||||
validator(_, value) {
|
]}
|
||||||
return validateArg(
|
|
||||||
editingNode.data,
|
|
||||||
arg,
|
|
||||||
value,
|
|
||||||
workspace.usingVars
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{!hasArgOptions(arg) && isStringType(type) && (
|
|
||||||
<TextArea autoSize disabled={disabled} onBlur={submit} />
|
|
||||||
)}
|
|
||||||
{!hasArgOptions(arg) && isJsonType(type) && (
|
|
||||||
<TextArea autoSize disabled={disabled} onBlur={submit} />
|
|
||||||
)}
|
|
||||||
{!hasArgOptions(arg) && isIntType(type) && (
|
|
||||||
<InputNumber
|
|
||||||
disabled={disabled}
|
|
||||||
onBlur={submit}
|
|
||||||
precision={0}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!hasArgOptions(arg) && isFloatType(type) && (
|
|
||||||
<InputNumber disabled={disabled} onBlur={submit} />
|
|
||||||
)}
|
|
||||||
{!hasArgOptions(arg) && isBoolType(type) && (
|
|
||||||
<Switch disabled={disabled} onChange={submit} />
|
|
||||||
)}
|
|
||||||
{!hasArgOptions(arg) && isExprType(type) && (
|
|
||||||
<Input disabled={disabled} onBlur={submit} />
|
|
||||||
)}
|
|
||||||
{hasArgOptions(arg) && (
|
|
||||||
<Select
|
|
||||||
showSearch
|
|
||||||
disabled={disabled}
|
|
||||||
onBlur={submit}
|
|
||||||
onChange={submit}
|
|
||||||
options={(arg.options ?? []).map((option) => {
|
|
||||||
return {
|
|
||||||
value: option.value,
|
|
||||||
label: `${option.name}(${option.value})`,
|
|
||||||
};
|
|
||||||
})}
|
|
||||||
filterOption={(value, option) => {
|
|
||||||
value = value.toUpperCase();
|
|
||||||
return !!option?.label
|
|
||||||
.toLocaleUpperCase()
|
|
||||||
.includes(value.toUpperCase());
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<MinusCircleOutlined
|
|
||||||
style={{ marginBottom: "6px" }}
|
|
||||||
onClick={() => {
|
|
||||||
remove(item.name);
|
|
||||||
submit();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
))}
|
|
||||||
<Form.Item
|
|
||||||
label={items.length === 0 ? arg.desc : undefined}
|
|
||||||
style={{
|
|
||||||
marginLeft: items.length === 0 ? undefined : "100px",
|
|
||||||
marginRight: items.length === 0 ? undefined : "18px",
|
|
||||||
alignItems: "end",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="dashed"
|
|
||||||
onClick={() => {
|
|
||||||
add(arg.default ?? isBoolType(type) ? false : "");
|
|
||||||
if (isBoolType(type)) {
|
|
||||||
submit();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{ width: "100%" }}
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
danger={items.length === 0 && !isNodeArgOptional(arg)}
|
|
||||||
>
|
>
|
||||||
{t("add")}
|
{!hasArgOptions(arg) && isStringType(type) && (
|
||||||
</Button>
|
<TextArea autoSize disabled={disabled} onBlur={submit} />
|
||||||
<Form.ErrorList errors={errors} />
|
)}
|
||||||
</Form.Item>
|
{!hasArgOptions(arg) && isJsonType(type) && (
|
||||||
</div>
|
<TextArea autoSize disabled={disabled} onBlur={submit} />
|
||||||
)}
|
)}
|
||||||
</Form.List>
|
{!hasArgOptions(arg) && isIntType(type) && (
|
||||||
</Form.Item>
|
<InputNumber disabled={disabled} onBlur={submit} precision={0} />
|
||||||
|
)}
|
||||||
|
{!hasArgOptions(arg) && isFloatType(type) && (
|
||||||
|
<InputNumber disabled={disabled} onBlur={submit} />
|
||||||
|
)}
|
||||||
|
{!hasArgOptions(arg) && isBoolType(type) && (
|
||||||
|
<Switch disabled={disabled} onChange={submit} />
|
||||||
|
)}
|
||||||
|
{!hasArgOptions(arg) && isExprType(type) && (
|
||||||
|
<Input disabled={disabled} onBlur={submit} />
|
||||||
|
)}
|
||||||
|
{hasArgOptions(arg) && (
|
||||||
|
<Select
|
||||||
|
showSearch
|
||||||
|
disabled={disabled}
|
||||||
|
onBlur={submit}
|
||||||
|
onChange={submit}
|
||||||
|
options={(arg.options ?? []).map((option) => {
|
||||||
|
return {
|
||||||
|
value: option.value,
|
||||||
|
label: `${option.name}(${option.value})`,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
filterOption={(value, option) => {
|
||||||
|
value = value.toUpperCase();
|
||||||
|
return !!option?.label
|
||||||
|
.toLocaleUpperCase()
|
||||||
|
.includes(value.toUpperCase());
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<MinusCircleOutlined
|
||||||
|
style={{ marginBottom: "6px" }}
|
||||||
|
onClick={() => {
|
||||||
|
remove(item.name);
|
||||||
|
submit();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
<Form.Item
|
||||||
|
label={items.length === 0 ? arg.desc : undefined}
|
||||||
|
style={{
|
||||||
|
marginLeft: items.length === 0 ? undefined : "100px",
|
||||||
|
marginRight: items.length === 0 ? undefined : "18px",
|
||||||
|
alignItems: "end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={() => {
|
||||||
|
add(arg.default ?? isBoolType(type) ? false : "");
|
||||||
|
if (isBoolType(type)) {
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
danger={items.length === 0 && !isNodeArgOptional(arg)}
|
||||||
|
>
|
||||||
|
{t("add")}
|
||||||
|
</Button>
|
||||||
|
<Form.ErrorList errors={errors} />
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Form.List>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
@@ -1264,7 +1294,7 @@ const NodeInspector: FC = () => {
|
|||||||
setFieldValue(`args.${arg.name}`, value);
|
setFieldValue(`args.${arg.name}`, value);
|
||||||
validateFields([inputName]);
|
validateFields([inputName]);
|
||||||
}
|
}
|
||||||
if (!checkOneof(getFieldValue(inputName) ?? "", value)) {
|
if (!checkOneof(arg, value, form.getFieldValue(inputName))) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
t("node.oneof.error", {
|
t("node.oneof.error", {
|
||||||
|
|||||||
+7
-2
@@ -307,7 +307,7 @@ export const checkNodeArg = (data: NodeData, conf: NodeDef, i: number, verbose?:
|
|||||||
}
|
}
|
||||||
if (arg.oneof !== undefined) {
|
if (arg.oneof !== undefined) {
|
||||||
const idx = conf.input?.findIndex((v) => v.startsWith(arg.oneof!)) ?? -1;
|
const idx = conf.input?.findIndex((v) => v.startsWith(arg.oneof!)) ?? -1;
|
||||||
if (!checkOneof(data.args?.[arg.name], data.input?.[idx])) {
|
if (!checkOneof(arg, data.args?.[arg.name], data.input?.[idx])) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
error(
|
error(
|
||||||
data,
|
data,
|
||||||
@@ -321,7 +321,12 @@ export const checkNodeArg = (data: NodeData, conf: NodeDef, i: number, verbose?:
|
|||||||
return !hasError;
|
return !hasError;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const checkOneof = (argValue: unknown, inputValue: unknown) => {
|
export const checkOneof = (arg: NodeArg, argValue: unknown, inputValue: unknown) => {
|
||||||
|
if (isNodeArgArray(arg)) {
|
||||||
|
if (argValue instanceof Array && argValue.length === 0) {
|
||||||
|
argValue = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
argValue = argValue === undefined ? "" : argValue;
|
argValue = argValue === undefined ? "" : argValue;
|
||||||
inputValue = inputValue ?? "";
|
inputValue = inputValue ?? "";
|
||||||
return (argValue !== "" && inputValue === "") || (argValue === "" && inputValue !== "");
|
return (argValue !== "" && inputValue === "") || (argValue === "" && inputValue !== "");
|
||||||
|
|||||||
Reference in new issue
Block a user