ServiceCardComponent.razor 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. @using RackPeek.Domain.Resources.Services
  2. @using RackPeek.Domain.Resources.Services.UseCases
  3. @inject UpdateServiceUseCase UpdateServiceUseCase
  4. @inject GetServiceUseCase GetServiceUseCase
  5. @inject DeleteServiceUseCase DeleteServiceUseCase
  6. @inject CloneServiceUseCase CloneServiceUseCase
  7. @inject NavigationManager Nav
  8. @inject RenameServiceUseCase RenameServiceUseCase
  9. <div class="border border-zinc-800 rounded p-4 bg-zinc-900">
  10. <div class="flex justify-between items-center mb-3">
  11. <NavLink href="@($"resources/services/{Service.Name}")" class="block">
  12. <div class="text-zinc-100 hover:text-emerald-300">
  13. @Service.Name
  14. </div>
  15. </NavLink>
  16. <div class="flex gap-3 text-xs">
  17. @if (!_isEditing)
  18. {
  19. <button class="text-zinc-400 hover:text-zinc-200"
  20. @onclick="BeginEdit">
  21. Edit
  22. </button>
  23. <button class="text-xs text-blue-400 hover:text-blue-300 transition"
  24. title="Rename service"
  25. @onclick="OpenRename">
  26. Rename
  27. </button>
  28. <button
  29. class="text-xs text-emerald-400 hover:text-emerald-300 transition"
  30. title="Clone service"
  31. @onclick="OpenClone">
  32. Clone
  33. </button>
  34. <button
  35. class="text-xs text-red-400 hover:text-red-300 transition"
  36. title="Delete server"
  37. @onclick="ConfirmDelete">
  38. Delete
  39. </button>
  40. }
  41. else
  42. {
  43. <button class="text-emerald-400 hover:text-emerald-300"
  44. @onclick="Save">
  45. Save
  46. </button>
  47. <button class="text-zinc-500 hover:text-zinc-300"
  48. @onclick="Cancel">
  49. Cancel
  50. </button>
  51. }
  52. </div>
  53. </div>
  54. <div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
  55. <!-- IP -->
  56. <div>
  57. <div class="text-zinc-400 mb-1">IP</div>
  58. @if (_isEditing)
  59. {
  60. <input class="input"
  61. @bind="_edit.Ip"/>
  62. }
  63. else if (!string.IsNullOrWhiteSpace(Service.Network?.Ip))
  64. {
  65. <div class="text-zinc-300">@Service.Network!.Ip</div>
  66. }
  67. </div>
  68. <!-- Port -->
  69. <div>
  70. <div class="text-zinc-400 mb-1">Port</div>
  71. @if (_isEditing)
  72. {
  73. <input type="number"
  74. class="input"
  75. @bind="_edit.Port"/>
  76. }
  77. else if (Service.Network?.Port.HasValue == true)
  78. {
  79. <div class="text-zinc-300">@Service.Network.Port</div>
  80. }
  81. </div>
  82. <!-- Protocol -->
  83. <div>
  84. <div class="text-zinc-400 mb-1">Protocol</div>
  85. @if (_isEditing)
  86. {
  87. <input class="input"
  88. @bind="_edit.Protocol"/>
  89. }
  90. else if (!string.IsNullOrWhiteSpace(Service.Network?.Protocol))
  91. {
  92. <div class="text-zinc-300">@Service.Network!.Protocol</div>
  93. }
  94. </div>
  95. <!-- URL -->
  96. <div>
  97. <div class="text-zinc-400 mb-1">URL</div>
  98. @if (_isEditing)
  99. {
  100. <input class="input"
  101. @bind="_edit.Url"/>
  102. }
  103. else if (!string.IsNullOrWhiteSpace(Service.Network?.Url))
  104. {
  105. <a href="@Service.Network!.Url"
  106. target="_blank"
  107. rel="noopener noreferrer"
  108. class="text-emerald-400 hover:underline break-all">
  109. @Service.Network.Url
  110. </a>
  111. }
  112. </div>
  113. <!-- Runs On -->
  114. <div>
  115. <div class="text-zinc-400 mb-1">Runs On</div>
  116. @if (_isEditing)
  117. {
  118. <button
  119. class="hover:text-emerald-400"
  120. title="Edit Runs On"
  121. @onclick="() => _selectParentOpen = true">
  122. @if (!string.IsNullOrWhiteSpace(Service.RunsOn))
  123. {
  124. @($"{Service.RunsOn} +")
  125. }
  126. else
  127. {
  128. @("Edit parent")
  129. }
  130. </button>
  131. }
  132. else if (!string.IsNullOrWhiteSpace(Service.RunsOn))
  133. {
  134. <NavLink href="@($"resources/systems/{Service.RunsOn}")"
  135. class="text-emerald-400">
  136. @Service.RunsOn
  137. </NavLink>
  138. }
  139. </div>
  140. </div>
  141. </div>
  142. <SystemSelectionModal
  143. IsOpen="@_selectParentOpen"
  144. IsOpenChanged="v => _selectParentOpen = v"
  145. Title="Select a parent"
  146. Value="@SelectedParentName"
  147. OnAccept="HandleParentSelected"/>
  148. <ConfirmModal
  149. IsOpen="_confirmDeleteOpen"
  150. IsOpenChanged="v => _confirmDeleteOpen = v"
  151. Title="Delete server"
  152. ConfirmText="Delete"
  153. ConfirmClass="bg-red-600 hover:bg-red-500"
  154. OnConfirm="DeleteServer">
  155. Are you sure you want to delete <strong>@Service.Name</strong>?
  156. </ConfirmModal>
  157. <StringValueModal
  158. IsOpen="_cloneOpen"
  159. IsOpenChanged="v => _cloneOpen = v"
  160. Title="Clone service"
  161. Description="Enter a name for the cloned service"
  162. Label="New service name"
  163. Value="@($"{Service.Name}-copy")"
  164. OnSubmit="HandleCloneSubmit" />
  165. <StringValueModal
  166. IsOpen="_renameOpen"
  167. IsOpenChanged="v => _renameOpen = v"
  168. Title="Rename service"
  169. Description="Enter a new name for this service"
  170. Label="New service name"
  171. Value="@Service.Name"
  172. OnSubmit="HandleRenameSubmit" />
  173. @code
  174. {
  175. bool _cloneOpen;
  176. void OpenClone()
  177. {
  178. _cloneOpen = true;
  179. }
  180. async Task HandleCloneSubmit(string newName)
  181. {
  182. await CloneServiceUseCase.ExecuteAsync(Service.Name, newName);
  183. Nav.NavigateTo($"resources/services/{newName}");
  184. }
  185. }
  186. @code {
  187. [Parameter] [EditorRequired] public Service Service { get; set; } = default!;
  188. [Parameter] public EventCallback<ServiceEditModel> OnSave { get; set; }
  189. private bool _isEditing;
  190. private ServiceEditModel _edit = new();
  191. void BeginEdit()
  192. {
  193. _edit = ServiceEditModel.From(Service);
  194. _isEditing = true;
  195. }
  196. async Task Save()
  197. {
  198. _isEditing = false;
  199. await OnSave.InvokeAsync(_edit);
  200. }
  201. void Cancel()
  202. {
  203. _isEditing = false;
  204. }
  205. bool _selectParentOpen;
  206. string? SelectedParentName;
  207. async Task HandleParentSelected(string? name)
  208. {
  209. SelectedParentName = name;
  210. await UpdateServiceUseCase.ExecuteAsync(
  211. Service.Name,
  212. Service.Network?.Ip,
  213. Service.Network?.Port,
  214. Service.Network?.Protocol,
  215. Service.Network?.Url,
  216. name);
  217. Service = await GetServiceUseCase.ExecuteAsync(Service.Name);
  218. _edit = ServiceEditModel.From(Service);
  219. }
  220. }
  221. <ConfirmModal
  222. IsOpen="_confirmDeleteOpen"
  223. IsOpenChanged="v => _confirmDeleteOpen = v"
  224. Title="Delete service"
  225. ConfirmText="Delete"
  226. ConfirmClass="bg-red-600 hover:bg-red-500"
  227. OnConfirm="DeleteServer">
  228. Are you sure you want to delete <strong>@Service.Name</strong>?
  229. <br/>
  230. </ConfirmModal>
  231. @code {
  232. private bool _confirmDeleteOpen;
  233. [Parameter] public EventCallback<string> OnDeleted { get; set; }
  234. void ConfirmDelete()
  235. {
  236. _confirmDeleteOpen = true;
  237. }
  238. async Task DeleteServer()
  239. {
  240. _confirmDeleteOpen = false;
  241. await DeleteServiceUseCase.ExecuteAsync(Service.Name);
  242. if (OnDeleted.HasDelegate)
  243. await OnDeleted.InvokeAsync(Service.Name);
  244. }
  245. }
  246. @code
  247. {
  248. bool _renameOpen;
  249. void OpenRename()
  250. {
  251. _renameOpen = true;
  252. }
  253. async Task HandleRenameSubmit(string newName)
  254. {
  255. await RenameServiceUseCase.ExecuteAsync(Service.Name, newName);
  256. Nav.NavigateTo($"resources/services/{newName}");
  257. }
  258. }