NodeInspector.tsx 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import React from "react";
  2. import styles from "./TopologyBuilder.module.css";
  3. import type { TopologyNode } from "./model";
  4. import MachineSelector from "../../assets/Selector/MachineSelector";
  5. import ModuleSlots from "../../assets/Selector/ModuleSlots";
  6. import BeaconConfigurator, { type BeaconGroup } from "../../assets/Selector/BeaconConfigurator";
  7. import { ContainerType } from "../simulator";
  8. export default function NodeInspector({ node, onChange }: { node: TopologyNode; onChange: (n: TopologyNode) => void }) {
  9. const updateName = (e: React.ChangeEvent<HTMLInputElement>) => onChange({ ...node, name: e.target.value });
  10. const updateMachineConfig = (updates: Partial<TopologyNode["machineConfig"]>) => {
  11. if (!node.machineConfig) return;
  12. onChange({
  13. ...node,
  14. machineConfig: { ...node.machineConfig, ...updates },
  15. });
  16. };
  17. return (
  18. <div className={styles.panel}>
  19. <h2>Edit {node.type}</h2>
  20. <div className={styles.formGroup}>
  21. <label>Node Name (ID: {node.id.split("_")[1]})</label>
  22. <input value={node.name} onChange={updateName} />
  23. </div>
  24. {node.type === ContainerType.Machine && node.machineConfig && (
  25. <div className={styles.machineConfig}>
  26. <div className={styles.formGroup}>
  27. <label>Multiplier (Parallel Instances)</label>
  28. <input
  29. type="number"
  30. min="1"
  31. value={node.machineConfig.multiplier}
  32. onChange={(e) => updateMachineConfig({ multiplier: parseInt(e.target.value, 10) || 1 })}
  33. />
  34. </div>
  35. <div className={styles.formGroup}>
  36. <label>Machine Type</label>
  37. <MachineSelector
  38. key={node.id}
  39. value={{
  40. machine: node.machineConfig.setup.machine,
  41. qualityLevel: node.machineConfig.setup.machineQualityLevel || 0,
  42. recipe: node.machineConfig.recipe,
  43. }}
  44. onChange={({ machine, qualityLevel, recipe }) =>
  45. updateMachineConfig({
  46. setup: {
  47. ...node.machineConfig!.setup,
  48. machine: machine as any,
  49. machineQualityLevel: qualityLevel,
  50. },
  51. recipe,
  52. })
  53. }
  54. />
  55. </div>
  56. <div className={styles.formGroup}>
  57. <label>Modules</label>
  58. <ModuleSlots
  59. value={node.machineConfig.setup.machineModules}
  60. maxSlots={node.machineConfig.setup.machine?.module_slots || 0}
  61. allowedEffects={node.machineConfig.setup.machine?.allowed_effects as string[]}
  62. onChange={(modules) =>
  63. updateMachineConfig({
  64. setup: { ...node.machineConfig!.setup, machineModules: modules },
  65. })
  66. }
  67. />
  68. </div>
  69. <div className={styles.formGroup}>
  70. <label>Beacons</label>
  71. <BeaconConfigurator
  72. groups={node.machineConfig.setup.beacons as BeaconGroup[]}
  73. onChange={(beacons) =>
  74. updateMachineConfig({
  75. setup: { ...node.machineConfig!.setup, beacons },
  76. })
  77. }
  78. />
  79. </div>
  80. </div>
  81. )}
  82. </div>
  83. );
  84. }