114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
|
import { useCollectionManager, useCompile } from "@nocobase/client";
|
||
|
|
||
|
import { instructions, useAvailableUpstreams, useNodeContext } from "./nodes";
|
||
|
import { useFlowContext } from "./FlowContext";
|
||
|
import { triggers } from "./triggers";
|
||
|
import { NAMESPACE } from "./locale";
|
||
|
|
||
|
export type VariableOption = { key: string, value: string; label: string; children?: VariableOption[] };
|
||
|
|
||
|
const VariableTypes = [
|
||
|
{
|
||
|
title: `{{t("Node result", { ns: "${NAMESPACE}" })}}`,
|
||
|
value: '$jobsMapByNodeId',
|
||
|
options(types) {
|
||
|
const current = useNodeContext();
|
||
|
const upstreams = useAvailableUpstreams(current);
|
||
|
const options: VariableOption[] = [];
|
||
|
upstreams.forEach((node) => {
|
||
|
const instruction = instructions.get(node.type);
|
||
|
const subOptions = instruction.getOptions?.(node.config, types);
|
||
|
if (subOptions) {
|
||
|
options.push({
|
||
|
key: node.id.toString(),
|
||
|
value: node.id.toString(),
|
||
|
label: node.title ?? `#${node.id}`,
|
||
|
children: subOptions,
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
return options;
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
title: `{{t("Trigger variables", { ns: "${NAMESPACE}" })}}`,
|
||
|
value: '$context',
|
||
|
options(types) {
|
||
|
const { workflow } = useFlowContext();
|
||
|
const trigger = triggers.get(workflow.type);
|
||
|
return trigger?.getOptions?.(workflow.config, types) ?? null;
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
title: `{{t("System variables", { ns: "${NAMESPACE}" })}}`,
|
||
|
value: '$system',
|
||
|
options: [
|
||
|
{
|
||
|
key: 'now',
|
||
|
value: 'now',
|
||
|
label: `{{t("Current time", { ns: "${NAMESPACE}" })}}`,
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
];
|
||
|
|
||
|
export const TypeSets = {
|
||
|
boolean: new Set(['boolean']),
|
||
|
number: new Set(['integer', 'bigInt', 'float', 'double', 'real', 'decimal']),
|
||
|
string: new Set(['string', 'text', 'password']),
|
||
|
date: new Set(['date', 'time'])
|
||
|
}
|
||
|
|
||
|
function matchFieldType(field, type): Boolean {
|
||
|
if (typeof type === 'string') {
|
||
|
return Boolean(TypeSets[type]?.has(field.type));
|
||
|
}
|
||
|
|
||
|
if (typeof type === 'object' && type.type === 'reference') {
|
||
|
return (field.collectionName === type.options?.collection && field.name === 'id')
|
||
|
|| (field.type === 'belongsTo' && field.target === type.options?.collection);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
export function filterTypedFields(fields, types) {
|
||
|
return types
|
||
|
? fields.filter(field => types.some(type => matchFieldType(field, type)))
|
||
|
: fields;
|
||
|
}
|
||
|
|
||
|
export function useWorkflowVariableOptions() {
|
||
|
const compile = useCompile();
|
||
|
const options = VariableTypes.map((item: any) => {
|
||
|
const options = typeof item.options === 'function' ? item.options().filter(Boolean) : item.options;
|
||
|
return {
|
||
|
label: compile(item.title),
|
||
|
value: item.value,
|
||
|
key: item.value,
|
||
|
children: compile(options),
|
||
|
disabled: options && !options.length
|
||
|
};
|
||
|
});
|
||
|
return options;
|
||
|
}
|
||
|
|
||
|
export function useCollectionFieldOptions(props) {
|
||
|
const { fields, collection, types } = props;
|
||
|
const compile = useCompile();
|
||
|
const { getCollectionFields } = useCollectionManager();
|
||
|
return filterTypedFields((fields ?? getCollectionFields(collection)), types)
|
||
|
.filter(field => field.interface && (!field.target || field.type === 'belongsTo'))
|
||
|
.map(field => field.type === 'belongsTo'
|
||
|
? {
|
||
|
label: `${compile(field.uiSchema?.title || field.name)} ID`,
|
||
|
key: field.foreignKey,
|
||
|
value: field.foreignKey,
|
||
|
}
|
||
|
: {
|
||
|
label: compile(field.uiSchema?.title || field.name),
|
||
|
key: field.name,
|
||
|
value: field.name,
|
||
|
});
|
||
|
}
|