function AddSubcommandDialog()

in src/web/src/views/workspace/WSEditorCommandContent.tsx [1543:1717]


function AddSubcommandDialog(props: {
  workspaceUrl: string;
  command: Command;
  argVar: string;
  subArgOptions: { var: string; options: string }[];
  defaultGroupNames: string[];
  open: boolean;
  onClose: (added: boolean) => void;
}) {
  const [updating, setUpdating] = useState<boolean>(false);
  const [invalidText, setInvalidText] = useState<string | undefined>(undefined);
  const [commandGroupName, setCommandGroupName] = useState<string>("");
  const [refArgsOptions, setRefArgsOptions] = useState<{ var: string; options: string }[]>([]);

  useEffect(() => {
    setCommandGroupName(props.defaultGroupNames.join(" "));
    setRefArgsOptions(props.subArgOptions);
  }, [props.argVar, props.defaultGroupNames]);

  const handleClose = () => {
    setInvalidText(undefined);
    props.onClose(false);
  };

  const verifyAddSubresource = () => {
    setInvalidText(undefined);
    const argOptions: { [argVar: string]: string[] } = {};
    let invalidText: string | undefined = undefined;
    refArgsOptions.forEach((arg, idx) => {
      const names = arg.options.split(" ").filter((n) => n.length > 0);
      if (names.length < 1) {
        invalidText = `Prop ${idx + 1} option name is required.`;
        return undefined;
      }

      for (const idx in names) {
        const piece = names[idx];
        if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(piece)) {
          invalidText = `Invalid 'Prop ${idx + 1} option name': '${piece}'. Supported regular expression is: [a-z0-9]+(-[a-z0-9]+)* `;
          return undefined;
        }
      }
      argOptions[arg.var] = names;
    });

    const names = commandGroupName.split(" ").filter((n) => n.length > 0);
    if (names.length < 1) {
      invalidText = "Invalid Command group name";
      return;
    }

    if (invalidText !== undefined) {
      setInvalidText(invalidText);
      return undefined;
    }

    return {
      commandGroupName: names.join(" "),
      refArgsOptions: argOptions,
    };
  };

  const handleAddSubresource = async () => {
    const urls = props.command.resources.map((resource) => {
      const resourceId = btoa(resource.id);
      const version = btoa(resource.version);
      return `${props.workspaceUrl}/Resources/${resourceId}/V/${version}/Subresources`;
    });

    if (urls.length !== 1) {
      setInvalidText(`Cannot create subcommands, command contains ${props.command.resources.length} resources`);
      return;
    }

    const data = verifyAddSubresource();
    if (data === undefined) {
      return;
    }

    setUpdating(true);

    try {
      await axios.post(urls[0], {
        ...data,
        arg: props.argVar,
      });
      props.onClose(true);
    } catch (err: any) {
      console.error(err);
      if (err.response?.data?.message) {
        const data = err.response!.data!;
        setInvalidText(`ResponseError: ${data.message!}: ${JSON.stringify(data.details)}`);
      }
      setUpdating(false);
    }
  };

  const buildRefArgText = (arg: { var: string; options: string }, idx: number) => {
    return (
      <TextField
        id={`subArg-${arg.var}`}
        key={arg.var}
        label={`${arg.var}`}
        helperText={idx === 0 ? "You can input multiple names separated by a space character" : undefined}
        type="text"
        fullWidth
        variant="standard"
        value={arg.options}
        onChange={(event: any) => {
          const options = refArgsOptions.map((value) => {
            if (value.var === arg.var) {
              return {
                ...value,
                options: event.target.value,
              };
            } else {
              return value;
            }
          });
          setRefArgsOptions(options);
        }}
        margin="normal"
        required
      />
    );
  };

  return (
    <Dialog disableEscapeKeyDown open={props.open} sx={{ "& .MuiDialog-paper": { width: "80%" } }}>
      <DialogTitle>Add Subcommands</DialogTitle>
      <DialogContent dividers={true}>
        {invalidText && (
          <Alert variant="filled" severity="error">
            {" "}
            {invalidText}{" "}
          </Alert>
        )}
        <FormLabel>Subcommand Group</FormLabel>
        <TextField
          id="subcommand-group-name"
          label="name"
          placeholder="Please input command group name for subcommands"
          type="text"
          variant="standard"
          value={commandGroupName}
          fullWidth
          margin="normal"
          required
          onChange={(event: any) => {
            setCommandGroupName(event.target.value);
          }}
        />
        {refArgsOptions.length > 0 && (
          <>
            <FormLabel>Argument Options</FormLabel>
            {refArgsOptions.map(buildRefArgText)}
          </>
        )}
      </DialogContent>
      <DialogActions>
        {updating && (
          <Box sx={{ width: "100%" }}>
            <LinearProgress color="secondary" />
          </Box>
        )}
        {!updating && (
          <>
            <Button onClick={handleClose}>Cancel</Button>
            <Button onClick={handleAddSubresource}>Add Subcommands</Button>
          </>
        )}
      </DialogActions>
    </Dialog>
  );
}