import type { ReactNode } from "react"; import { useI18n } from "../i18n"; import { HOP_VENDORS, defaultHopTemplate, expandBastionHopFields, isAutoHopTemplate, isBastionHopVendor, isLinuxHopVendor, patchHopVendorChange, type HopTargetAuthMode, type HopVendor, } from "../utils/hopProxy"; export type HopProxyFieldsState = { hop_vendor: HopVendor; hop_host: string; hop_port: number; hop_protocol: string; hop_username: string; hop_password: string; hop_command_template: string; hop_vrf: string; hop_target_auth_mode: HopTargetAuthMode; hop_enter_system_view: boolean; }; export const emptyHopProxyFields = (): HopProxyFieldsState => ({ hop_vendor: "zte", hop_host: "", hop_port: 22, hop_protocol: "ssh", hop_username: "", hop_password: "", hop_command_template: defaultHopTemplate("zte", "ssh", ""), hop_vrf: "", hop_target_auth_mode: "bastion_managed", hop_enter_system_view: false, }); function FormLabel({ children, required }: { children: ReactNode; required?: boolean }) { return ( {children} {required ? ( {" "} * ) : null} ); } function applyHopTemplate( prev: HopProxyFieldsState, protocol: string, vrf: string, force = false, ): Partial { if (!force && !isAutoHopTemplate(prev.hop_command_template, prev.hop_vendor, prev.hop_protocol, prev.hop_vrf)) { return {}; } return { hop_command_template: defaultHopTemplate(prev.hop_vendor, protocol, vrf) }; } function hopHintKey(vendor: string): string { const v = String(vendor || "").toLowerCase(); if (v === "bastion") return "managedNe.hop.bastionHint"; if (v === "linux") return "managedNe.hop.linuxHint"; if (v === "huawei") return "managedNe.hop.huaweiHint"; if (v === "cisco") return "managedNe.hop.ciscoHint"; return "managedNe.hop.zteHint"; } function templateHintKey(vendor: string): string { const v = String(vendor || "").toLowerCase(); if (v === "bastion") return "managedNe.hop.templateHintBastion"; if (v === "huawei") return "managedNe.hop.templateHintHuawei"; if (v === "cisco") return "managedNe.hop.templateHintCisco"; return "managedNe.hop.templateHint"; } function vrfLabelKey(vendor: string): string { const v = String(vendor || "").toLowerCase(); if (v === "huawei") return "managedNe.hop.vpnInstance"; if (v === "cisco") return "managedNe.hop.vrfCisco"; return "managedNe.hop.vrf"; } type Props = { value: HopProxyFieldsState; onChange: (patch: Partial) => void; hopPasswordRequired?: boolean; hopPasswordOptional?: boolean; }; export function HopProxyFields({ value, onChange, hopPasswordRequired = true, hopPasswordOptional = false, }: Props) { const { t } = useI18n(); const linux = isLinuxHopVendor(value.hop_vendor); const bastion = isBastionHopVendor(value.hop_vendor); const huawei = value.hop_vendor === "huawei"; const cliHop = !linux && !bastion; const set = (patch: Partial) => onChange(patch); return ( {t("managedNe.hop.type")} { const hop_vendor = e.target.value as HopVendor; set(patchHopVendorChange(hop_vendor, value)); }} > {HOP_VENDORS.map((v) => ( {t(`managedNe.hop.vendor.${v}`)} ))} {t(hopHintKey(value.hop_vendor))} {t("managedNe.hop.host")} set({ hop_host: e.target.value })} onBlur={() => { if (!bastion) return; const raw = String(value.hop_host || "").trim(); if (!raw.includes("@")) return; const parsed = expandBastionHopFields(raw, value.hop_username); if (!parsed.hop_host || parsed.hop_host === raw) return; set({ hop_host: parsed.hop_host, hop_username: parsed.hop_username || value.hop_username, }); }} /> {bastion ? {t("managedNe.hop.hostHintBastion")} : null} {t("managedNe.hop.port")} set({ hop_port: Number(e.target.value) || 22 })} /> {bastion ? ( {t("managedNe.hop.targetAuthMode")} set({ hop_target_auth_mode: e.target.value as HopTargetAuthMode })} > {t("managedNe.hop.targetAuthBastionManaged")} {t("managedNe.hop.targetAuthManual")} {t("managedNe.hop.targetAuthHint")} ) : null} {cliHop ? ( {t("managedNe.hop.protocol")} { const hop_protocol = e.target.value; set({ hop_protocol, ...applyHopTemplate(value, hop_protocol, value.hop_vrf) }); }} > {huawei ? t("managedNe.hop.protocolSshStelnet") : "ssh"} telnet ) : null} {t("managedNe.hop.username")} set({ hop_username: e.target.value })} /> {t("managedNe.hop.password")} {hopPasswordOptional ? ( ({t("managedNe.form.passwordOptional")}) ) : null} set({ hop_password: e.target.value })} /> {bastion ? ( {t("managedNe.hop.usernameTemplate")} set({ hop_command_template: e.target.value })} placeholder={defaultHopTemplate(value.hop_vendor, value.hop_protocol, value.hop_vrf)} /> {t(templateHintKey(value.hop_vendor))} ) : null} {cliHop ? ( <> {t(vrfLabelKey(value.hop_vendor))} { const hop_vrf = e.target.value; set({ hop_vrf, ...applyHopTemplate(value, value.hop_protocol, hop_vrf) }); }} /> {huawei ? ( {t("managedNe.hop.enterSystemView")} set({ hop_enter_system_view: e.target.value === "yes" })} > {t("managedNe.hop.enterSystemViewNo")} {t("managedNe.hop.enterSystemViewYes")} {t("managedNe.hop.enterSystemViewHint")} ) : null} {t("managedNe.hop.commandTemplate")} set({ hop_command_template: e.target.value })} placeholder={defaultHopTemplate(value.hop_vendor, value.hop_protocol, value.hop_vrf)} /> {t(templateHintKey(value.hop_vendor))} > ) : null} ); }