in src/web/src/views/workspace/WSEditorCommandArgumentsContent.tsx [212:431]
function ArgumentNavigation(props: {
commandUrl: string;
args: CMDArg[];
clsArgDefineMap: ClsArgDefinitionMap;
onEdit: (arg: CMDArg, argIdxStack: ArgIdx[]) => void;
onFlatten: (arg: CMDArg, argIdxStack: ArgIdx[]) => void;
onUnwrap: (arg: CMDArg, argIdxStack: ArgIdx[]) => void;
onAddSubcommand: (arg: CMDArg, argIdxStack: ArgIdx[]) => void;
}) {
const [argIdxStack, setArgIdxStack] = useState<ArgIdx[]>([]);
const getArgProps = (
selectedArgBase: CMDArgBase,
): { title: string; props: CMDArg[]; flattenArgVar: string | undefined } | undefined => {
if (selectedArgBase.type.startsWith("@")) {
const clsArgDefine = props.clsArgDefineMap[(selectedArgBase as CMDClsArgBase).clsName];
const clsArgProps = getArgProps(clsArgDefine);
if (clsArgProps !== undefined && clsArgDefine.type === "object") {
clsArgProps!.flattenArgVar = (selectedArgBase as CMDClsArg).var;
}
return clsArgProps;
}
if (selectedArgBase.type === "object") {
return {
title: "Props",
props: (selectedArgBase as CMDObjectArgBase).args,
flattenArgVar: (selectedArgBase as CMDObjectArg).var,
};
} else if (selectedArgBase.type.startsWith("dict<")) {
const item = (selectedArgBase as CMDDictArgBase).item;
const itemProps = item ? getArgProps(item) : undefined;
if (!itemProps) {
return undefined;
}
return {
title: "Dict Element Props",
props: itemProps.props,
flattenArgVar: undefined,
};
} else if (selectedArgBase.type.startsWith("array<")) {
const itemProps = getArgProps((selectedArgBase as CMDArrayArgBase).item);
if (!itemProps) {
return undefined;
}
return {
title: "Array Element Props",
props: itemProps.props,
flattenArgVar: undefined,
};
} else {
return undefined;
}
};
const getSelectedArg = (stack: ArgIdx[]): CMDArg | undefined => {
if (stack.length === 0) {
return undefined;
} else {
let args: CMDArg[] = [...props.args];
let selectedArg: CMDArg | undefined = undefined;
for (const i in stack) {
const argVar = stack[i].var;
selectedArg = args.find((arg) => arg.var === argVar);
if (!selectedArg) {
break;
}
args = getArgProps(selectedArg)?.props ?? [];
}
return selectedArg;
}
};
useEffect(() => {
setArgIdxStack([]);
}, [props.commandUrl]);
useEffect(() => {
// update argument idx stack
const stack = [...argIdxStack];
while (stack.length > 0 && !getSelectedArg(stack)) {
stack.pop();
}
setArgIdxStack(stack);
}, [props.args, props.clsArgDefineMap]);
const handleSelectSubArg = (subArgVar: string) => {
let subArg;
if (argIdxStack.length > 0) {
const arg = getSelectedArg(argIdxStack);
if (!arg) {
return;
}
subArg = getArgProps(arg)?.props.find((a) => a.var === subArgVar);
} else {
subArg = props.args.find((a) => a.var === subArgVar);
}
if (!subArg) {
return;
}
const argIdx: ArgIdx = {
var: subArg.var,
displayKey: subArg.options[0],
};
if (argIdxStack.length === 0) {
if (argIdx.displayKey.length === 1) {
argIdx.displayKey = `-${argIdx.displayKey}`;
} else {
argIdx.displayKey = `--${argIdx.displayKey}`;
}
}
let argType = subArg.type;
if (argType.startsWith("@")) {
argType = props.clsArgDefineMap[(subArg as CMDClsArg).clsName].type;
}
if (argType.startsWith("dict<")) {
argIdx.displayKey += "{}";
} else if (argType.startsWith("array<")) {
argIdx.displayKey += "[]";
}
setArgIdxStack([...argIdxStack, argIdx]);
};
const handleChangeArgIdStack = (end: number) => {
setArgIdxStack(argIdxStack.slice(0, end));
};
const buildArgumentReviewer = () => {
const selectedArg = getSelectedArg(argIdxStack);
if (!selectedArg) {
return <></>;
}
const stage = selectedArg.stage;
return (
<React.Fragment>
<Box
sx={{
display: "flex",
flexDirection: "row",
alignItems: "flex-start",
justifyContent: "flex-start",
}}
>
<ArgNavBar argIdxStack={argIdxStack} onChangeArgIdStack={handleChangeArgIdStack} />
{stage === "Stable" && <StableTypography sx={{ flexShrink: 0 }}>{stage}</StableTypography>}
{stage === "Preview" && <PreviewTypography sx={{ flexShrink: 0 }}>{stage}</PreviewTypography>}
{stage === "Experimental" && <ExperimentalTypography sx={{ flexShrink: 0 }}>{stage}</ExperimentalTypography>}
</Box>
<ArgumentReviewer
arg={selectedArg}
depth={argIdxStack.length}
onEdit={() => {
props.onEdit(selectedArg, argIdxStack);
}}
onUnwrap={() => {
props.onUnwrap(selectedArg, argIdxStack);
}}
/>
</React.Fragment>
);
};
const buildArgumentPropsReviewer = () => {
if (argIdxStack.length === 0) {
if (props.args.length === 0) {
return <></>;
}
return (
<ArgumentPropsReviewer
title={"Argument Groups"}
args={props.args}
onFlatten={undefined}
onAddSubcommand={undefined}
depth={argIdxStack.length}
onSelectSubArg={handleSelectSubArg}
/>
);
} else {
const selectedArg = getSelectedArg(argIdxStack);
if (!selectedArg) {
return <></>;
}
const argProps = getArgProps(selectedArg);
if (!argProps) {
return <></>;
}
const canFlatten = argProps.flattenArgVar !== undefined;
return (
<ArgumentPropsReviewer
title={argProps.title}
args={argProps.props}
depth={argIdxStack.length}
selectedArg={selectedArg!}
onFlatten={
canFlatten
? () => {
props.onFlatten(selectedArg!, argIdxStack);
}
: undefined
}
onAddSubcommand={() => {
props.onAddSubcommand(selectedArg!, argIdxStack);
}}
onSelectSubArg={handleSelectSubArg}
/>
);
}
};
return (
<React.Fragment>
{argIdxStack.length > 0 && <React.Fragment>{buildArgumentReviewer()}</React.Fragment>}
<React.Fragment>{buildArgumentPropsReviewer()}</React.Fragment>
</React.Fragment>
);
}