ServerCardComponent.razor 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. @using RackPeek.Domain.Resources.Hardware.Models
  2. @using RackPeek.Domain.Resources.Hardware.Servers
  3. @using RackPeek.Domain.Resources.Hardware.Servers.Cpus
  4. @using RackPeek.Domain.Resources.Hardware.Servers.Drives
  5. @using RackPeek.Domain.Resources.Hardware.Servers.Gpus
  6. @using RackPeek.Domain.Resources.Hardware.Servers.Nics
  7. @using RackPeek.Web.Components.Modals
  8. @inject AddCpuUseCase AddCpuUseCase
  9. @inject RemoveCpuUseCase RemoveCpuUseCase
  10. @inject UpdateCpuUseCase UpdateCpuUseCase
  11. @inject AddDrivesUseCase AddDriveUseCase
  12. @inject RemoveDriveUseCase RemoveDriveUseCase
  13. @inject UpdateDriveUseCase UpdateDriveUseCase
  14. @inject AddNicUseCase AddNicUseCase
  15. @inject UpdateNicUseCase UpdateNicUseCase
  16. @inject RemoveNicUseCase RemoveNicUseCase
  17. @inject AddGpuUseCase AddGpuUseCase
  18. @inject UpdateGpuUseCase UpdateGpuUseCase
  19. @inject RemoveGpuUseCase RemoveGpuUseCase
  20. @inject GetServerUseCase GetServerUseCase
  21. @inject UpdateServerUseCase UpdateServerUseCase
  22. <div class="border border-zinc-800 rounded p-4 bg-zinc-900">
  23. <div class="flex justify-between items-center mb-3">
  24. <div class="text-zinc-100">
  25. @Server.Name
  26. </div>
  27. @if (Server.Ipmi == true)
  28. {
  29. <span class="text-xs text-emerald-400">IPMI</span>
  30. }
  31. </div>
  32. <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
  33. <div>
  34. <div class="flex items-center justify-between mb-1 group">
  35. <div class="text-zinc-400">CPU
  36. <button
  37. class="hover:text-emerald-400 group-hover:opacity-100 transition"
  38. title="Add CPU"
  39. @onclick="OpenAddCpu">
  40. +
  41. </button>
  42. </div>
  43. </div>
  44. @if (Server.Cpus?.Any() == true)
  45. {
  46. <!-- CPU rows -->
  47. @foreach (var cpu in Server.Cpus)
  48. {
  49. <div
  50. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  51. <div class="flex gap-2 group-hover:opacity-100 transition">
  52. <button
  53. class="hover:text-emerald-400"
  54. title="Edit CPU"
  55. @onclick="() => OpenEditCpu(cpu)">
  56. @cpu.Model — @cpu.Cores cores / @cpu.Threads threads
  57. </button>
  58. </div>
  59. </div>
  60. }
  61. }
  62. </div>
  63. <div>
  64. <div class="text-zinc-400 mb-1">RAM
  65. @if (Server.Ram is null)
  66. {
  67. <button
  68. class="hover:text-emerald-400 group-hover:opacity-100 transition"
  69. title="Add RAM"
  70. @onclick="EditRam">
  71. +
  72. </button>
  73. }
  74. </div>
  75. @if (Server.Ram is not null)
  76. {
  77. <div
  78. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  79. <div class="flex gap-2 group-hover:opacity-100 transition">
  80. <button
  81. class="hover:text-emerald-400"
  82. title="Edit RAM"
  83. @onclick="EditRam">
  84. @($"{Server.Ram.Size} GB {@Server.Ram.Mts} MT/s")
  85. </button>
  86. </div>
  87. </div>
  88. }
  89. </div>
  90. <div>
  91. <div class="flex items-center justify-between mb-1 group">
  92. <div class="text-zinc-400">Drives
  93. <button
  94. class="hover:text-emerald-400 group-hover:opacity-100 transition"
  95. title="Add Drive"
  96. @onclick="OpenAddDrive">
  97. +
  98. </button>
  99. </div>
  100. </div>
  101. @if (Server.Drives?.Any() == true)
  102. {
  103. @foreach (var drive in Server.Drives)
  104. {
  105. <div
  106. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  107. <div class="flex gap-2 group-hover:opacity-100 transition">
  108. <button
  109. class="hover:text-emerald-400"
  110. title="Edit Drive"
  111. @onclick="() => OpenEditDrives(drive)">
  112. @drive.Type — @drive.Size GB
  113. </button>
  114. </div>
  115. </div>
  116. }
  117. }
  118. </div>
  119. <div>
  120. <div class="flex items-center justify-between mb-1 group">
  121. <div class="text-zinc-400">
  122. NICs
  123. <button
  124. class="hover:text-emerald-400 group-hover:opacity-100 transition"
  125. title="Add NIC"
  126. @onclick="OpenAddNic">
  127. +
  128. </button>
  129. </div>
  130. </div>
  131. @if (Server.Nics?.Any() == true)
  132. {
  133. @foreach (var nic in Server.Nics)
  134. {
  135. <div
  136. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  137. <button
  138. class="hover:text-emerald-400"
  139. title="Edit NIC"
  140. @onclick="() => OpenEditNic(nic)">
  141. @nic.Type — @nic.Speed Gbps (@nic.Ports ports)
  142. </button>
  143. </div>
  144. }
  145. }
  146. </div>
  147. <div>
  148. <div class="flex items-center justify-between mb-1 group">
  149. <div class="text-zinc-400">
  150. GPUs
  151. <button
  152. class="hover:text-emerald-400 group-hover:opacity-100 transition"
  153. title="Add GPU"
  154. @onclick="OpenAddGpu">
  155. +
  156. </button>
  157. </div>
  158. </div>
  159. @if (Server.Gpus?.Any() == true)
  160. {
  161. @foreach (var gpu in Server.Gpus)
  162. {
  163. <div
  164. class="flex items-center justify-between text-zinc-300 group hover:bg-zinc-800/40 rounded px-1 py-0.5">
  165. <button
  166. class="hover:text-emerald-400"
  167. title="Edit GPU"
  168. @onclick="() => OpenEditGpu(gpu)">
  169. @gpu.Model — @gpu.Vram GB VRAM
  170. </button>
  171. </div>
  172. }
  173. }
  174. </div>
  175. </div>
  176. </div>
  177. <CpuModal
  178. IsOpen="@_cpuModalOpen"
  179. IsOpenChanged="v => _cpuModalOpen = v"
  180. Value="@_editingCpu"
  181. OnSubmit="HandleCpuSubmit"
  182. OnDelete="HandleCpuDelete"/>
  183. <RamModal
  184. IsOpen="@_isRamModalOpen"
  185. IsOpenChanged="v => _isRamModalOpen = v"
  186. Value="@Server.Ram"
  187. OnSubmit="HandleRamSubmit"/>
  188. <DriveModal
  189. IsOpen="@_driveModalOpen"
  190. IsOpenChanged="v => _driveModalOpen = v"
  191. Value="@_editingDrive"
  192. OnSubmit="HandleDriveSubmit"
  193. OnDelete="HandleDriveDelete"/>
  194. <NicModal
  195. IsOpen="@_nicModalOpen"
  196. IsOpenChanged="v => _nicModalOpen = v"
  197. Value="@_editingNic"
  198. OnSubmit="HandleNicSubmit"
  199. OnDelete="HandleNicDelete" />
  200. <GpuModal
  201. IsOpen="@_gpuModalOpen"
  202. IsOpenChanged="v => _gpuModalOpen = v"
  203. Value="@_editingGpu"
  204. OnSubmit="HandleGpuSubmit"
  205. OnDelete="HandleGpuDelete" />
  206. @code {
  207. [Parameter] [EditorRequired]
  208. public Server Server { get; set; } = default!;
  209. #region RAM
  210. private bool _isRamModalOpen;
  211. private void EditRam()
  212. {
  213. _isRamModalOpen = true;
  214. }
  215. private async Task HandleRamSubmit(Ram value)
  216. {
  217. _isRamModalOpen = false;
  218. await UpdateServerUseCase.ExecuteAsync(Server.Name, value.Size, value.Mts, Server.Ipmi);
  219. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  220. }
  221. #endregion
  222. #region CPU
  223. bool _cpuModalOpen;
  224. int _editingCpuIndex;
  225. Cpu? _editingCpu;
  226. void OpenAddCpu()
  227. {
  228. _editingCpuIndex = -1;
  229. _editingCpu = null;
  230. _cpuModalOpen = true;
  231. }
  232. void OpenEditCpu(Cpu cpu)
  233. {
  234. _editingCpu = cpu;
  235. Server.Cpus ??= new();
  236. _editingCpuIndex = Server.Cpus.IndexOf(cpu);;
  237. _cpuModalOpen = true;
  238. }
  239. async Task HandleCpuSubmit(Cpu cpu)
  240. {
  241. Server.Cpus ??= new();
  242. if (_editingCpuIndex < 0)
  243. {
  244. await AddCpuUseCase.ExecuteAsync(Server.Name, cpu.Model, cpu.Cores, cpu.Threads);
  245. }
  246. else
  247. {
  248. await UpdateCpuUseCase.ExecuteAsync(Server.Name, _editingCpuIndex, cpu.Model, cpu.Cores, cpu.Threads);
  249. }
  250. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  251. }
  252. async Task HandleCpuDelete(Cpu cpu)
  253. {
  254. await RemoveCpuUseCase.ExecuteAsync(Server.Name, _editingCpuIndex);
  255. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  256. }
  257. #endregion
  258. #region Drives
  259. bool _driveModalOpen;
  260. int _editingDriveIndex;
  261. Drive? _editingDrive;
  262. void OpenAddDrive()
  263. {
  264. _editingDriveIndex = -1;
  265. _editingDrive = null;
  266. _driveModalOpen = true;
  267. }
  268. void OpenEditDrives(Drive drive)
  269. {
  270. _editingDrive = drive;
  271. Server.Drives ??= new();
  272. _editingDriveIndex = Server.Drives.IndexOf(drive);;
  273. _driveModalOpen = true;
  274. }
  275. async Task HandleDriveSubmit(Drive drive)
  276. {
  277. Server.Drives ??= new();
  278. if (_editingDriveIndex < 0)
  279. {
  280. await AddDriveUseCase.ExecuteAsync(Server.Name, drive.Type, drive.Size);
  281. }
  282. else
  283. {
  284. await UpdateDriveUseCase.ExecuteAsync(Server.Name, _editingDriveIndex, drive.Type, drive.Size);
  285. }
  286. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  287. StateHasChanged();
  288. }
  289. async Task HandleDriveDelete(Drive drive)
  290. {
  291. await RemoveDriveUseCase.ExecuteAsync(Server.Name, _editingDriveIndex);
  292. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  293. StateHasChanged();
  294. }
  295. #endregion
  296. #region NICs
  297. bool _nicModalOpen;
  298. int _editingNicIndex;
  299. Nic? _editingNic;
  300. void OpenAddNic()
  301. {
  302. _editingNicIndex = -1;
  303. _editingNic = null;
  304. _nicModalOpen = true;
  305. }
  306. void OpenEditNic(Nic nic)
  307. {
  308. Server.Nics ??= new();
  309. _editingNicIndex = Server.Nics.IndexOf(nic);
  310. _editingNic = nic;
  311. _nicModalOpen = true;
  312. }
  313. async Task HandleNicSubmit(Nic nic)
  314. {
  315. Server.Nics ??= new();
  316. if (_editingNicIndex < 0)
  317. {
  318. await AddNicUseCase.ExecuteAsync(
  319. Server.Name,
  320. nic.Type,
  321. nic.Speed,
  322. nic.Ports);
  323. }
  324. else
  325. {
  326. await UpdateNicUseCase.ExecuteAsync(
  327. Server.Name,
  328. _editingNicIndex,
  329. nic.Type,
  330. nic.Speed,
  331. nic.Ports);
  332. }
  333. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  334. }
  335. async Task HandleNicDelete(Nic nic)
  336. {
  337. await RemoveNicUseCase.ExecuteAsync(Server.Name, _editingNicIndex);
  338. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  339. }
  340. #endregion
  341. #region GPUs
  342. bool _gpuModalOpen;
  343. int _editingGpuIndex;
  344. Gpu? _editingGpu;
  345. void OpenAddGpu()
  346. {
  347. _editingGpuIndex = -1;
  348. _editingGpu = null;
  349. _gpuModalOpen = true;
  350. }
  351. void OpenEditGpu(Gpu gpu)
  352. {
  353. Server.Gpus ??= new();
  354. _editingGpuIndex = Server.Gpus.IndexOf(gpu);
  355. _editingGpu = gpu;
  356. _gpuModalOpen = true;
  357. }
  358. async Task HandleGpuSubmit(Gpu gpu)
  359. {
  360. Server.Gpus ??= new();
  361. if (_editingGpuIndex < 0)
  362. {
  363. await AddGpuUseCase.ExecuteAsync(
  364. Server.Name,
  365. gpu.Model,
  366. gpu.Vram);
  367. }
  368. else
  369. {
  370. await UpdateGpuUseCase.ExecuteAsync(
  371. Server.Name,
  372. _editingGpuIndex,
  373. gpu.Model,
  374. gpu.Vram);
  375. }
  376. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  377. }
  378. async Task HandleGpuDelete(Gpu gpu)
  379. {
  380. await RemoveGpuUseCase.ExecuteAsync(Server.Name, _editingGpuIndex);
  381. Server = await GetServerUseCase.ExecuteAsync(Server.Name);
  382. }
  383. #endregion
  384. }