ServiceCardComponent.razor 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. @typeparam TService where TService : RackPeek.Domain.Resources.Services.Service
  2. <div class="border border-zinc-800 rounded p-4 bg-zinc-900">
  3. <div class="flex justify-between items-center mb-3">
  4. <div class="text-zinc-100">
  5. @Service.Name
  6. </div>
  7. <div class="flex gap-3 text-xs">
  8. @if (!_isEditing)
  9. {
  10. <button class="text-zinc-400 hover:text-zinc-200"
  11. @onclick="BeginEdit">
  12. Edit
  13. </button>
  14. }
  15. else
  16. {
  17. <button class="text-emerald-400 hover:text-emerald-300"
  18. @onclick="Save">
  19. Save
  20. </button>
  21. <button class="text-zinc-500 hover:text-zinc-300"
  22. @onclick="Cancel">
  23. Cancel
  24. </button>
  25. }
  26. </div>
  27. </div>
  28. <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
  29. <!-- IP -->
  30. <div>
  31. <div class="text-zinc-400 mb-1">IP</div>
  32. @if (_isEditing)
  33. {
  34. <input class="input"
  35. @bind="_edit.Ip"/>
  36. }
  37. else if (!string.IsNullOrWhiteSpace(Service.Network?.Ip))
  38. {
  39. <div class="text-zinc-300">@Service.Network!.Ip</div>
  40. }
  41. </div>
  42. <!-- Port -->
  43. <div>
  44. <div class="text-zinc-400 mb-1">Port</div>
  45. @if (_isEditing)
  46. {
  47. <input type="number"
  48. class="input"
  49. @bind="_edit.Port"/>
  50. }
  51. else if (Service.Network?.Port.HasValue == true)
  52. {
  53. <div class="text-zinc-300">@Service.Network.Port</div>
  54. }
  55. </div>
  56. <!-- Protocol -->
  57. <div>
  58. <div class="text-zinc-400 mb-1">Protocol</div>
  59. @if (_isEditing)
  60. {
  61. <input class="input"
  62. @bind="_edit.Protocol"/>
  63. }
  64. else if (!string.IsNullOrWhiteSpace(Service.Network?.Protocol))
  65. {
  66. <div class="text-zinc-300">@Service.Network!.Protocol</div>
  67. }
  68. </div>
  69. <!-- URL -->
  70. <div>
  71. <div class="text-zinc-400 mb-1">URL</div>
  72. @if (_isEditing)
  73. {
  74. <input class="input"
  75. @bind="_edit.Url"/>
  76. }
  77. else if (!string.IsNullOrWhiteSpace(Service.Network?.Url))
  78. {
  79. <a href="@Service.Network!.Url"
  80. target="_blank"
  81. rel="noopener noreferrer"
  82. class="text-emerald-400 hover:underline break-all">
  83. @Service.Network.Url
  84. </a>
  85. }
  86. </div>
  87. <!-- Runs On -->
  88. <div>
  89. <div class="text-zinc-400 mb-1">Runs On</div>
  90. @if (_isEditing)
  91. {
  92. <input class="input"
  93. @bind="_edit.RunsOn"/>
  94. }
  95. else if (!string.IsNullOrWhiteSpace(Service.RunsOn))
  96. {
  97. <NavLink href="@($"/resources/systems/{Service.RunsOn}")"
  98. class="text-emerald-400">
  99. @Service.RunsOn
  100. </NavLink>
  101. }
  102. </div>
  103. </div>
  104. </div>
  105. @code {
  106. [Parameter][EditorRequired] public TService Service { get; set; } = default!;
  107. [Parameter] public EventCallback<ServiceEditModel> OnSave { get; set; }
  108. private bool _isEditing;
  109. private ServiceEditModel _edit = new();
  110. void BeginEdit()
  111. {
  112. _edit = ServiceEditModel.From(Service);
  113. _isEditing = true;
  114. }
  115. async Task Save()
  116. {
  117. _isEditing = false;
  118. await OnSave.InvokeAsync(_edit);
  119. }
  120. void Cancel()
  121. {
  122. _isEditing = false;
  123. }
  124. }