@flightctl/ui-components 1.1.0-rc1 → 1.1.0-rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/dist/src/components/Repository/CreateRepository/CreateRepositoryForm.css +5 -1
  2. package/dist/types/imagebuilder/index.d.ts +2 -0
  3. package/dist/types/imagebuilder/index.d.ts.map +1 -1
  4. package/dist/types/imagebuilder/index.js +3 -1
  5. package/dist/types/imagebuilder/index.js.map +1 -1
  6. package/dist/types/imagebuilder/models/ApiVersion.d.ts +8 -0
  7. package/dist/types/imagebuilder/models/ApiVersion.d.ts.map +1 -0
  8. package/dist/types/imagebuilder/models/ApiVersion.js +16 -0
  9. package/dist/types/imagebuilder/models/ApiVersion.js.map +1 -0
  10. package/dist/types/imagebuilder/models/ImageBuild.d.ts +2 -4
  11. package/dist/types/imagebuilder/models/ImageBuild.d.ts.map +1 -1
  12. package/dist/types/imagebuilder/models/ImageBuildList.d.ts +2 -4
  13. package/dist/types/imagebuilder/models/ImageBuildList.d.ts.map +1 -1
  14. package/dist/types/imagebuilder/models/ImageExport.d.ts +2 -4
  15. package/dist/types/imagebuilder/models/ImageExport.d.ts.map +1 -1
  16. package/dist/types/imagebuilder/models/ImageExportList.d.ts +2 -4
  17. package/dist/types/imagebuilder/models/ImageExportList.d.ts.map +1 -1
  18. package/dist/types/imagebuilder/models/Status.d.ts +28 -0
  19. package/dist/types/imagebuilder/models/Status.d.ts.map +1 -0
  20. package/dist/types/imagebuilder/models/Status.js +3 -0
  21. package/dist/types/imagebuilder/models/Status.js.map +1 -0
  22. package/dist/types/index.d.ts +8 -0
  23. package/dist/types/index.d.ts.map +1 -1
  24. package/dist/types/index.js +3 -1
  25. package/dist/types/index.js.map +1 -1
  26. package/dist/types/models/ApiVersion.d.ts +9 -0
  27. package/dist/types/models/ApiVersion.d.ts.map +1 -0
  28. package/dist/types/models/ApiVersion.js +17 -0
  29. package/dist/types/models/ApiVersion.js.map +1 -0
  30. package/dist/types/models/ApplicationProviderBase.d.ts +12 -0
  31. package/dist/types/models/ApplicationProviderBase.d.ts.map +1 -0
  32. package/dist/types/models/ApplicationProviderBase.js +3 -0
  33. package/dist/types/models/ApplicationProviderBase.js.map +1 -0
  34. package/dist/types/models/ApplicationProviderSpec.d.ts +5 -15
  35. package/dist/types/models/ApplicationProviderSpec.d.ts.map +1 -1
  36. package/dist/types/models/ApplicationUser.d.ts +7 -0
  37. package/dist/types/models/ApplicationUser.d.ts.map +1 -0
  38. package/dist/types/models/ApplicationUser.js +3 -0
  39. package/dist/types/models/ApplicationUser.js.map +1 -0
  40. package/dist/types/models/AuthConfig.d.ts +2 -4
  41. package/dist/types/models/AuthConfig.d.ts.map +1 -1
  42. package/dist/types/models/AuthProvider.d.ts +2 -4
  43. package/dist/types/models/AuthProvider.d.ts.map +1 -1
  44. package/dist/types/models/AuthProviderList.d.ts +2 -4
  45. package/dist/types/models/AuthProviderList.d.ts.map +1 -1
  46. package/dist/types/models/CertificateSigningRequest.d.ts +2 -4
  47. package/dist/types/models/CertificateSigningRequest.d.ts.map +1 -1
  48. package/dist/types/models/CertificateSigningRequestList.d.ts +2 -4
  49. package/dist/types/models/CertificateSigningRequestList.d.ts.map +1 -1
  50. package/dist/types/models/ComposeApplication.d.ts +7 -0
  51. package/dist/types/models/ComposeApplication.d.ts.map +1 -0
  52. package/dist/types/models/ComposeApplication.js +3 -0
  53. package/dist/types/models/ComposeApplication.js.map +1 -0
  54. package/dist/types/models/ContainerApplication.d.ts +18 -0
  55. package/dist/types/models/ContainerApplication.d.ts.map +1 -0
  56. package/dist/types/models/ContainerApplication.js +3 -0
  57. package/dist/types/models/ContainerApplication.js.map +1 -0
  58. package/dist/types/models/ContainerApplicationProperties.d.ts +13 -0
  59. package/dist/types/models/ContainerApplicationProperties.d.ts.map +1 -0
  60. package/dist/types/models/ContainerApplicationProperties.js +3 -0
  61. package/dist/types/models/ContainerApplicationProperties.js.map +1 -0
  62. package/dist/types/models/Device.d.ts +2 -4
  63. package/dist/types/models/Device.d.ts.map +1 -1
  64. package/dist/types/models/DeviceList.d.ts +2 -4
  65. package/dist/types/models/DeviceList.d.ts.map +1 -1
  66. package/dist/types/models/EnrollmentRequest.d.ts +2 -4
  67. package/dist/types/models/EnrollmentRequest.d.ts.map +1 -1
  68. package/dist/types/models/EnrollmentRequestList.d.ts +2 -4
  69. package/dist/types/models/EnrollmentRequestList.d.ts.map +1 -1
  70. package/dist/types/models/Event.d.ts +2 -4
  71. package/dist/types/models/Event.d.ts.map +1 -1
  72. package/dist/types/models/Event.js.map +1 -1
  73. package/dist/types/models/EventList.d.ts +2 -4
  74. package/dist/types/models/EventList.d.ts.map +1 -1
  75. package/dist/types/models/Fleet.d.ts +2 -4
  76. package/dist/types/models/Fleet.d.ts.map +1 -1
  77. package/dist/types/models/FleetList.d.ts +2 -4
  78. package/dist/types/models/FleetList.d.ts.map +1 -1
  79. package/dist/types/models/HelmApplication.d.ts +20 -0
  80. package/dist/types/models/HelmApplication.d.ts.map +1 -0
  81. package/dist/types/models/HelmApplication.js +3 -0
  82. package/dist/types/models/HelmApplication.js.map +1 -0
  83. package/dist/types/models/ImageApplicationProviderSpec.d.ts +2 -22
  84. package/dist/types/models/ImageApplicationProviderSpec.d.ts.map +1 -1
  85. package/dist/types/models/InlineApplicationProviderSpec.d.ts +2 -3
  86. package/dist/types/models/InlineApplicationProviderSpec.d.ts.map +1 -1
  87. package/dist/types/models/Organization.d.ts +2 -4
  88. package/dist/types/models/Organization.d.ts.map +1 -1
  89. package/dist/types/models/OrganizationList.d.ts +2 -4
  90. package/dist/types/models/OrganizationList.d.ts.map +1 -1
  91. package/dist/types/models/QuadletApplication.d.ts +8 -0
  92. package/dist/types/models/QuadletApplication.d.ts.map +1 -0
  93. package/dist/types/models/QuadletApplication.js +3 -0
  94. package/dist/types/models/QuadletApplication.js.map +1 -0
  95. package/dist/types/models/Repository.d.ts +2 -4
  96. package/dist/types/models/Repository.d.ts.map +1 -1
  97. package/dist/types/models/RepositoryList.d.ts +2 -4
  98. package/dist/types/models/RepositoryList.d.ts.map +1 -1
  99. package/dist/types/models/ResourceSync.d.ts +2 -4
  100. package/dist/types/models/ResourceSync.d.ts.map +1 -1
  101. package/dist/types/models/ResourceSyncList.d.ts +2 -4
  102. package/dist/types/models/ResourceSyncList.d.ts.map +1 -1
  103. package/dist/types/models/Status.d.ts +2 -4
  104. package/dist/types/models/Status.d.ts.map +1 -1
  105. package/dist/types/models/TemplateVersion.d.ts +2 -4
  106. package/dist/types/models/TemplateVersion.d.ts.map +1 -1
  107. package/dist/types/models/TemplateVersionList.d.ts +2 -4
  108. package/dist/types/models/TemplateVersionList.d.ts.map +1 -1
  109. package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.d.ts.map +1 -1
  110. package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.js +51 -51
  111. package/dist/ui-components/src/components/AuthProvider/CreateAuthProvider/utils.js.map +1 -1
  112. package/dist/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.js +1 -1
  113. package/dist/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.js.map +1 -1
  114. package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.d.ts.map +1 -1
  115. package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.js +5 -4
  116. package/dist/ui-components/src/components/Device/DeviceDetails/DeviceDetailsPage.js.map +1 -1
  117. package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.d.ts.map +1 -1
  118. package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.js +5 -1
  119. package/dist/ui-components/src/components/Device/DeviceDetails/TerminalTab.js.map +1 -1
  120. package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.d.ts +3 -3
  121. package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.d.ts.map +1 -1
  122. package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.js +310 -363
  123. package/dist/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.js.map +1 -1
  124. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.d.ts +1 -3
  125. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.d.ts.map +1 -1
  126. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.js +18 -19
  127. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.js.map +1 -1
  128. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.d.ts +1 -3
  129. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.d.ts.map +1 -1
  130. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.js +5 -4
  131. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.js.map +1 -1
  132. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.d.ts +1 -3
  133. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.d.ts.map +1 -1
  134. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.js +2 -2
  135. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.js.map +1 -1
  136. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.d.ts +3 -3
  137. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.d.ts.map +1 -1
  138. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.js +20 -23
  139. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.js.map +1 -1
  140. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.js +3 -3
  141. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.js.map +1 -1
  142. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.d.ts.map +1 -1
  143. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js +25 -45
  144. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js.map +1 -1
  145. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.d.ts +8 -0
  146. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.d.ts.map +1 -0
  147. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.js +37 -0
  148. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.js.map +1 -0
  149. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.d.ts +1 -3
  150. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.d.ts.map +1 -1
  151. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.js +5 -8
  152. package/dist/ui-components/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.js.map +1 -1
  153. package/dist/ui-components/src/components/Device/EditDeviceWizard/utils.d.ts +18 -18
  154. package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.d.ts +4 -2
  155. package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.d.ts.map +1 -1
  156. package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.js +2 -2
  157. package/dist/ui-components/src/components/ErrorAlert/ErrorAlert.js.map +1 -1
  158. package/dist/ui-components/src/components/Fleet/CreateFleet/utils.d.ts +1 -1
  159. package/dist/ui-components/src/components/Fleet/CreateFleet/utils.d.ts.map +1 -1
  160. package/dist/ui-components/src/components/Fleet/CreateFleet/utils.js +3 -3
  161. package/dist/ui-components/src/components/Fleet/CreateFleet/utils.js.map +1 -1
  162. package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.d.ts.map +1 -1
  163. package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.js +3 -1
  164. package/dist/ui-components/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.js.map +1 -1
  165. package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.d.ts +7 -0
  166. package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.d.ts.map +1 -0
  167. package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.js +40 -0
  168. package/dist/ui-components/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.js.map +1 -0
  169. package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.d.ts +8 -0
  170. package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.d.ts.map +1 -0
  171. package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.js +37 -0
  172. package/dist/ui-components/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.js.map +1 -0
  173. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.d.ts.map +1 -1
  174. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.js +4 -3
  175. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.js.map +1 -1
  176. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.js +1 -1
  177. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.js.map +1 -1
  178. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.d.ts.map +1 -1
  179. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.js +13 -10
  180. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.js.map +1 -1
  181. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.d.ts.map +1 -1
  182. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.js +4 -2
  183. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.js.map +1 -1
  184. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.d.ts.map +1 -1
  185. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.js +7 -1
  186. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.js.map +1 -1
  187. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/types.d.ts +3 -5
  188. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/types.d.ts.map +1 -1
  189. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.d.ts +3 -2
  190. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.d.ts.map +1 -1
  191. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.js +139 -34
  192. package/dist/ui-components/src/components/ImageBuilds/CreateImageBuildWizard/utils.js.map +1 -1
  193. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.d.ts.map +1 -1
  194. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.js +23 -12
  195. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.js.map +1 -1
  196. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.d.ts.map +1 -1
  197. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.js +115 -39
  198. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.js.map +1 -1
  199. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.d.ts +1 -0
  200. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.d.ts.map +1 -1
  201. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.js +17 -18
  202. package/dist/ui-components/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.js.map +1 -1
  203. package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.d.ts +5 -2
  204. package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.d.ts.map +1 -1
  205. package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.js +22 -12
  206. package/dist/ui-components/src/components/ImageBuilds/ImageBuildRow.js.map +1 -1
  207. package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.d.ts.map +1 -1
  208. package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.js +17 -8
  209. package/dist/ui-components/src/components/ImageBuilds/ImageBuildsPage.js.map +1 -1
  210. package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.d.ts +10 -9
  211. package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.d.ts.map +1 -1
  212. package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.js +122 -26
  213. package/dist/ui-components/src/components/ImageBuilds/ImageExportCards.js.map +1 -1
  214. package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.d.ts +2 -1
  215. package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.d.ts.map +1 -1
  216. package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.js +10 -4
  217. package/dist/ui-components/src/components/Repository/CreateRepository/CreateRepositoryForm.js.map +1 -1
  218. package/dist/ui-components/src/components/Repository/CreateRepository/utils.d.ts.map +1 -1
  219. package/dist/ui-components/src/components/Repository/CreateRepository/utils.js +3 -4
  220. package/dist/ui-components/src/components/Repository/CreateRepository/utils.js.map +1 -1
  221. package/dist/ui-components/src/components/form/RepositorySelect.d.ts.map +1 -1
  222. package/dist/ui-components/src/components/form/RepositorySelect.js +1 -1
  223. package/dist/ui-components/src/components/form/RepositorySelect.js.map +1 -1
  224. package/dist/ui-components/src/components/form/UploadField.d.ts.map +1 -1
  225. package/dist/ui-components/src/components/form/UploadField.js +25 -16
  226. package/dist/ui-components/src/components/form/UploadField.js.map +1 -1
  227. package/dist/ui-components/src/components/form/validations.d.ts +25 -18
  228. package/dist/ui-components/src/components/form/validations.d.ts.map +1 -1
  229. package/dist/ui-components/src/components/form/validations.js +79 -33
  230. package/dist/ui-components/src/components/form/validations.js.map +1 -1
  231. package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.d.ts +2 -1
  232. package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.d.ts.map +1 -1
  233. package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.js +2 -2
  234. package/dist/ui-components/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.js.map +1 -1
  235. package/dist/ui-components/src/constants.d.ts +5 -6
  236. package/dist/ui-components/src/constants.d.ts.map +1 -1
  237. package/dist/ui-components/src/constants.js +19 -11
  238. package/dist/ui-components/src/constants.js.map +1 -1
  239. package/dist/ui-components/src/hooks/useWebSocket.d.ts.map +1 -1
  240. package/dist/ui-components/src/hooks/useWebSocket.js +25 -4
  241. package/dist/ui-components/src/hooks/useWebSocket.js.map +1 -1
  242. package/dist/ui-components/src/types/deviceSpec.d.ts +44 -76
  243. package/dist/ui-components/src/types/deviceSpec.d.ts.map +1 -1
  244. package/dist/ui-components/src/types/deviceSpec.js +13 -26
  245. package/dist/ui-components/src/types/deviceSpec.js.map +1 -1
  246. package/dist/ui-components/src/types/extraTypes.d.ts +1 -7
  247. package/dist/ui-components/src/types/extraTypes.d.ts.map +1 -1
  248. package/dist/ui-components/src/types/extraTypes.js.map +1 -1
  249. package/dist/ui-components/src/types/rbac.d.ts +7 -1
  250. package/dist/ui-components/src/types/rbac.d.ts.map +1 -1
  251. package/dist/ui-components/src/types/rbac.js +6 -0
  252. package/dist/ui-components/src/types/rbac.js.map +1 -1
  253. package/dist/ui-components/src/utils/imageBuilds.d.ts +1 -0
  254. package/dist/ui-components/src/utils/imageBuilds.d.ts.map +1 -1
  255. package/dist/ui-components/src/utils/imageBuilds.js +20 -29
  256. package/dist/ui-components/src/utils/imageBuilds.js.map +1 -1
  257. package/dist/ui-components/src/utils/search.d.ts +2 -1
  258. package/dist/ui-components/src/utils/search.d.ts.map +1 -1
  259. package/dist/ui-components/src/utils/search.js +2 -2
  260. package/dist/ui-components/src/utils/search.js.map +1 -1
  261. package/package.json +2 -2
  262. package/src/components/AuthProvider/CreateAuthProvider/utils.ts +2 -2
  263. package/src/components/DetailsPage/Tables/ApplicationsTable.tsx +2 -2
  264. package/src/components/Device/DeviceDetails/DeviceDetailsPage.tsx +10 -4
  265. package/src/components/Device/DeviceDetails/TerminalTab.tsx +9 -1
  266. package/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts +361 -425
  267. package/src/components/Device/EditDeviceWizard/steps/ApplicationContainerForm.tsx +19 -29
  268. package/src/components/Device/EditDeviceWizard/steps/ApplicationHelmForm.tsx +5 -13
  269. package/src/components/Device/EditDeviceWizard/steps/ApplicationImageForm.tsx +2 -16
  270. package/src/components/Device/EditDeviceWizard/steps/ApplicationInlineForm.tsx +8 -7
  271. package/src/components/Device/EditDeviceWizard/steps/ApplicationIntegritySettings.tsx +5 -5
  272. package/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.tsx +29 -101
  273. package/src/components/Device/EditDeviceWizard/steps/ApplicationVariablesForm.tsx +87 -0
  274. package/src/components/Device/EditDeviceWizard/steps/ApplicationVolumeForm.tsx +5 -10
  275. package/src/components/ErrorAlert/ErrorAlert.tsx +13 -3
  276. package/src/components/Fleet/CreateFleet/utils.ts +4 -5
  277. package/src/components/Fleet/ImportFleetWizard/steps/RepositoryStep.tsx +11 -8
  278. package/src/components/ImageBuilds/CancelImageBuildModal/CancelImageBuildModal.tsx +81 -0
  279. package/src/components/ImageBuilds/ConfirmImageExportModal/ConfirmImageExportModal.tsx +61 -0
  280. package/src/components/ImageBuilds/CreateImageBuildWizard/CreateImageBuildWizard.tsx +8 -3
  281. package/src/components/ImageBuilds/CreateImageBuildWizard/steps/OutputImageStep.tsx +1 -1
  282. package/src/components/ImageBuilds/CreateImageBuildWizard/steps/RegistrationStep.tsx +18 -10
  283. package/src/components/ImageBuilds/CreateImageBuildWizard/steps/ReviewStep.tsx +5 -1
  284. package/src/components/ImageBuilds/CreateImageBuildWizard/steps/SourceImageStep.tsx +13 -1
  285. package/src/components/ImageBuilds/CreateImageBuildWizard/types.ts +3 -6
  286. package/src/components/ImageBuilds/CreateImageBuildWizard/utils.ts +161 -37
  287. package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildDetailsPage.tsx +36 -17
  288. package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildExportsGallery.tsx +131 -44
  289. package/src/components/ImageBuilds/ImageBuildDetails/ImageBuildLogsTab.tsx +22 -26
  290. package/src/components/ImageBuilds/ImageBuildRow.tsx +41 -20
  291. package/src/components/ImageBuilds/ImageBuildsPage.tsx +34 -15
  292. package/src/components/ImageBuilds/ImageExportCards.tsx +198 -80
  293. package/src/components/Repository/CreateRepository/CreateRepositoryForm.css +5 -1
  294. package/src/components/Repository/CreateRepository/CreateRepositoryForm.tsx +14 -4
  295. package/src/components/Repository/CreateRepository/utils.ts +4 -4
  296. package/src/components/form/RepositorySelect.tsx +1 -0
  297. package/src/components/form/UploadField.tsx +29 -30
  298. package/src/components/form/validations.ts +156 -106
  299. package/src/components/modals/CreateRepositoryModal/CreateRepositoryModal.tsx +3 -1
  300. package/src/constants.ts +19 -6
  301. package/src/hooks/useWebSocket.ts +25 -3
  302. package/src/types/deviceSpec.ts +68 -108
  303. package/src/types/extraTypes.ts +2 -12
  304. package/src/types/rbac.ts +6 -0
  305. package/src/utils/imageBuilds.ts +22 -32
  306. package/src/utils/search.ts +2 -2
@@ -10,31 +10,25 @@ import {
10
10
  AppSpecType,
11
11
  BatchForm,
12
12
  BatchLimitType,
13
- ComposeImageAppForm,
14
- ComposeInlineAppForm,
13
+ ComposeAppForm,
15
14
  DisruptionBudgetForm,
16
15
  GitConfigTemplate,
17
- HelmImageAppForm,
16
+ HelmAppForm,
18
17
  HttpConfigTemplate,
19
18
  InlineConfigTemplate,
19
+ InlineFileForm,
20
20
  KubeSecretTemplate,
21
21
  PortMapping,
22
- QuadletImageAppForm,
23
- QuadletInlineAppForm,
22
+ QuadletAppForm,
24
23
  RolloutPolicyForm,
25
24
  SpecConfigTemplate,
26
25
  SystemdUnitFormValue,
27
26
  UpdatePolicyForm,
28
27
  getAppIdentifier,
29
- isComposeImageAppForm,
30
28
  isGitConfigTemplate,
31
- isHelmImageAppForm,
32
29
  isHttpConfigTemplate,
33
30
  isInlineConfigTemplate,
34
31
  isKubeSecretTemplate,
35
- isQuadletImageAppForm,
36
- isQuadletInlineAppForm,
37
- isSingleContainerAppForm,
38
32
  } from '../../types/deviceSpec';
39
33
  import { labelToString } from '../../utils/labels';
40
34
  import { UpdateScheduleMode } from '../../utils/time';
@@ -53,9 +47,9 @@ const K8S_DNS_SUBDOMAIN_START_END = /^[a-z0-9](.*[a-z0-9])?$/;
53
47
  const K8S_DNS_SUBDOMAIN_ALLOWED_CHARACTERS = /^[a-z0-9.-]*$/;
54
48
  const K8S_DNS_SUBDOMAIN_VALUE_MAX_LENGTH = 253;
55
49
 
56
- // https://issues.redhat.com/browse/MGMT-18349 to make the validation more robust
57
- const BASIC_DEVICE_OS_IMAGE_REGEXP = /^[a-zA-Z0-9.\-\/:@_+]*$/;
58
- const APPLICATION_IMAGE_REGEXP = BASIC_DEVICE_OS_IMAGE_REGEXP;
50
+ const OCI_IMAGE_FULL_REGEXP = /^(?![./_])[a-zA-Z0-9.\-\/:@_+]*$/;
51
+ // Accepts all characters from the above regex, but it rejects leading dot, slash, or underscore
52
+ const OCI_IMAGE_ALLOWED_CHARS_REGEXP = /^[a-zA-Z0-9.\-\/:@_+]*$/;
59
53
  const APPLICATION_NAME_REGEXP = /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/;
60
54
  const APPLICATION_VAR_NAME_REGEXP = /^[a-zA-Z_]+[a-zA-Z0-9_]*$/;
61
55
 
@@ -74,6 +68,9 @@ const relativePathRegex = /^(?!\.\.\/|\.\.\$|\.\/)(\.\/)*[\w.-]+(?:\/[\w.-]+)*\/
74
68
  export const MAX_TARGET_REVISION_LENGTH = 244;
75
69
  const MAX_FILE_PATH_LENGTH = 253;
76
70
 
71
+ const HELM_NAMESPACE_MAX_LENGTH = 63;
72
+ const HELM_VALUES_FILE_EXT_REGEXP = /\.(yaml|yml)$/i;
73
+
77
74
  const isInteger = (val: number | undefined) => val === undefined || Number.isInteger(val);
78
75
 
79
76
  const validComposeFileNames = [
@@ -233,6 +230,23 @@ export const validApplicationAndVolumeName = (t: TFunction) =>
233
230
  t('Use lowercase alphanumeric characters, or dash (-). Must start and end with an alphanumeric character.'),
234
231
  );
235
232
 
233
+ export const getBuildNameValidations = (t: TFunction) => [
234
+ {
235
+ key: 'imageBuildName',
236
+ message: t(
237
+ 'Use lowercase alphanumeric characters, or dash (-). Must start and end with an alphanumeric character.',
238
+ ),
239
+ },
240
+ ];
241
+
242
+ export const validImageBuildName = (t: TFunction) =>
243
+ Yup.string()
244
+ .required(t('Build name is required'))
245
+ .test('imageBuildName', function (value: string | undefined) {
246
+ if (!value) return true;
247
+ return APPLICATION_NAME_REGEXP.test(value) || this.createError({ message: { imageBuildName: 'failed' } });
248
+ });
249
+
236
250
  export const maxLengthString = (t: TFunction, props: { maxLength: number; fieldName: string }) =>
237
251
  Yup.string().max(props.maxLength, t('{{ fieldName }} must not exceed {{ maxLength }} characters', props));
238
252
 
@@ -261,10 +275,52 @@ export const validOsImage = (t: TFunction, { isFleet }: { isFleet: boolean }) =>
261
275
  }
262
276
  }
263
277
 
264
- return BASIC_DEVICE_OS_IMAGE_REGEXP.test(validateOsImage);
278
+ return OCI_IMAGE_FULL_REGEXP.test(validateOsImage);
265
279
  },
266
280
  );
267
281
 
282
+ export const validHelmNamespace = (t: TFunction) =>
283
+ Yup.string()
284
+ .max(
285
+ HELM_NAMESPACE_MAX_LENGTH,
286
+ t('Namespace must not exceed {{ max }} characters.', { max: HELM_NAMESPACE_MAX_LENGTH }),
287
+ )
288
+ .test(
289
+ 'helm-namespace-format',
290
+ t(
291
+ 'Namespace must only include lowercase letters, numbers, and hyphens. It must start and end with a letter or number.',
292
+ ),
293
+ (value) => {
294
+ return !value || APPLICATION_NAME_REGEXP.test(value);
295
+ },
296
+ );
297
+
298
+ export const validHelmValuesFile = (t: TFunction) =>
299
+ Yup.string().test('helm-values-file', function (filename) {
300
+ if (!filename) {
301
+ return true;
302
+ }
303
+ if (filename.length > MAX_FILE_PATH_LENGTH) {
304
+ return this.createError({
305
+ message: t('Values file path must not exceed {{ max }} characters.', {
306
+ max: MAX_FILE_PATH_LENGTH,
307
+ }),
308
+ });
309
+ }
310
+ if (filename.startsWith('/') || filename.includes('..')) {
311
+ return this.createError({
312
+ message: t('Values file path must be relative and cannot contain parent directory references (..).'),
313
+ });
314
+ }
315
+
316
+ if (!HELM_VALUES_FILE_EXT_REGEXP.test(filename)) {
317
+ return this.createError({
318
+ message: t('Values file must have .yaml or .yml extension.'),
319
+ });
320
+ }
321
+ return true;
322
+ });
323
+
268
324
  export const validLabelsSchema = (t: TFunction, forbiddenLabels?: string[]) =>
269
325
  Yup.array()
270
326
  .of(
@@ -370,11 +426,7 @@ const inlineAppFileSchema = (t: TFunction) =>
370
426
 
371
427
  // Common test for unique file paths in inline applications
372
428
  const uniqueFilePathsTest =
373
- (t: TFunction) =>
374
- (
375
- files: (QuadletInlineAppForm | ComposeInlineAppForm)['files'] | undefined,
376
- testContext: Yup.TestContext<Yup.AnyObject>,
377
- ) => {
429
+ (t: TFunction) => (files: InlineFileForm[] | undefined, testContext: Yup.TestContext<Yup.AnyObject>) => {
378
430
  if (!files || files.length === 0) {
379
431
  return true;
380
432
  }
@@ -412,34 +464,33 @@ const uniqueFilePathsTest =
412
464
  });
413
465
  };
414
466
 
415
- const composeFileName =
416
- (t: TFunction) => (files: ComposeInlineAppForm['files'], testContext: Yup.TestContext<Yup.AnyObject>) => {
417
- const invalidFiles = files
418
- .map((file, index) => {
419
- if (!file.path) {
420
- return null;
421
- }
422
- // Extract filename from relative path (get last part after slash, or use whole path if no slash)
423
- const fileName = file.path.includes('/') ? file.path.split('/').pop() || file.path : file.path;
424
- if (!validComposeFileNames.includes(fileName)) {
425
- return index;
426
- }
467
+ const composeFileName = (t: TFunction) => (files: InlineFileForm[], testContext: Yup.TestContext<Yup.AnyObject>) => {
468
+ const invalidFiles = files
469
+ .map((file, index) => {
470
+ if (!file.path) {
427
471
  return null;
428
- })
429
- .filter((index): index is number => index !== null);
472
+ }
473
+ // Extract filename from relative path (get last part after slash, or use whole path if no slash)
474
+ const fileName = file.path.includes('/') ? file.path.split('/').pop() || file.path : file.path;
475
+ if (!validComposeFileNames.includes(fileName)) {
476
+ return index;
477
+ }
478
+ return null;
479
+ })
480
+ .filter((index): index is number => index !== null);
430
481
 
431
- if (invalidFiles.length > 0) {
432
- const firstInvalidIndex = invalidFiles[0];
433
- return testContext.createError({
434
- path: `${testContext.path}[${firstInvalidIndex}].path`,
435
- message: () =>
436
- t('File name must be one of: {{ allowedFileNames }}', {
437
- allowedFileNames: validComposeFileNameDisplay,
438
- }),
439
- });
440
- }
441
- return true;
442
- };
482
+ if (invalidFiles.length > 0) {
483
+ const firstInvalidIndex = invalidFiles[0];
484
+ return testContext.createError({
485
+ path: `${testContext.path}[${firstInvalidIndex}].path`,
486
+ message: () =>
487
+ t('File name must be one of: {{ allowedFileNames }}', {
488
+ allowedFileNames: validComposeFileNameDisplay,
489
+ }),
490
+ });
491
+ }
492
+ return true;
493
+ };
443
494
 
444
495
  // Helper to extract file extension from a path
445
496
  const getFileExtension = (path: string): string => {
@@ -454,7 +505,7 @@ const isAtRoot = (path: string): boolean => {
454
505
 
455
506
  // Validation for quadlet applications: checks for unsupported types first, then requires at least one supported type
456
507
  const quadletFileTypesValidation =
457
- (t: TFunction) => (files: QuadletInlineAppForm['files'], testContext: Yup.TestContext<Yup.AnyObject>) => {
508
+ (t: TFunction) => (files: InlineFileForm[], testContext: Yup.TestContext<Yup.AnyObject>) => {
458
509
  if (!files || files.length === 0) {
459
510
  return true; // This is handled by the min(1) requirement
460
511
  }
@@ -512,36 +563,35 @@ const quadletFileTypesValidation =
512
563
  };
513
564
 
514
565
  // Validation for quadlet applications: quadlet files must be at root level
515
- const quadletFilesAtRoot =
516
- (t: TFunction) => (files: QuadletInlineAppForm['files'], testContext: Yup.TestContext<Yup.AnyObject>) => {
517
- if (!files || files.length === 0) {
518
- return true;
519
- }
566
+ const quadletFilesAtRoot = (t: TFunction) => (files: InlineFileForm[], testContext: Yup.TestContext<Yup.AnyObject>) => {
567
+ if (!files || files.length === 0) {
568
+ return true;
569
+ }
520
570
 
521
- const invalidFiles = files
522
- .map((file, index) => {
523
- if (!file.path) {
524
- return null;
525
- }
526
- const ext = getFileExtension(file.path);
527
- // Only check files with supported quadlet extensions
528
- if (supportedQuadletExtensions.includes(ext) && !isAtRoot(file.path)) {
529
- return index;
530
- }
571
+ const invalidFiles = files
572
+ .map((file, index) => {
573
+ if (!file.path) {
531
574
  return null;
532
- })
533
- .filter((index): index is number => index !== null);
575
+ }
576
+ const ext = getFileExtension(file.path);
577
+ // Only check files with supported quadlet extensions
578
+ if (supportedQuadletExtensions.includes(ext) && !isAtRoot(file.path)) {
579
+ return index;
580
+ }
581
+ return null;
582
+ })
583
+ .filter((index): index is number => index !== null);
534
584
 
535
- if (invalidFiles.length > 0) {
536
- const firstInvalidIndex = invalidFiles[0];
537
- return testContext.createError({
538
- path: `${testContext.path}[${firstInvalidIndex}].path`,
539
- message: () => t('Quadlet files must be at root level (no subdirectories)'),
540
- });
541
- }
585
+ if (invalidFiles.length > 0) {
586
+ const firstInvalidIndex = invalidFiles[0];
587
+ return testContext.createError({
588
+ path: `${testContext.path}[${firstInvalidIndex}].path`,
589
+ message: () => t('Quadlet files must be at root level (no subdirectories)'),
590
+ });
591
+ }
542
592
 
543
- return true;
544
- };
593
+ return true;
594
+ };
545
595
 
546
596
  const PORT_NUMBER_REGEXP = /^\d+$/;
547
597
  const MAX_PORT = 65535;
@@ -621,17 +671,27 @@ export const validateMemoryLimit = (memory: string | undefined): boolean => {
621
671
  return true;
622
672
  };
623
673
 
624
- // Common volume validation helpers
625
- const volumeNameSchema = (t: TFunction) => validApplicationAndVolumeName(t).required(t('Volume name is required'));
626
-
627
- const optionalImageRefSchema = (t: TFunction) =>
628
- Yup.string().test('image-ref-format', t('Image reference includes invalid characters.'), (value) => {
629
- if (!value || value.length === 0) {
630
- return true; // Empty is allowed
674
+ const ociImageSchema = (t: TFunction) =>
675
+ Yup.string().test('oci-image-format', (value, testContext) => {
676
+ if (!value) return true;
677
+ if (!OCI_IMAGE_ALLOWED_CHARS_REGEXP.test(value)) {
678
+ return testContext.createError({
679
+ message: t('Image includes invalid characters.'),
680
+ });
681
+ }
682
+ if (!OCI_IMAGE_FULL_REGEXP.test(value)) {
683
+ return testContext.createError({
684
+ message: t('Image must not start with a dot (.), slash (/), or underscore (_).'),
685
+ });
631
686
  }
632
- return APPLICATION_IMAGE_REGEXP.test(value);
687
+ return true;
633
688
  });
634
689
 
690
+ const requiredOciImageSchema = (t: TFunction, requiredMessage?: string) =>
691
+ ociImageSchema(t).required(requiredMessage || t('Image is required.'));
692
+
693
+ const volumeNameSchema = (t: TFunction) => validApplicationAndVolumeName(t).required(t('Volume name is required'));
694
+
635
695
  const imagePullPolicySchema = (t: TFunction) =>
636
696
  Yup.string()
637
697
  .oneOf(
@@ -645,12 +705,11 @@ const mountPathSchema = (t: TFunction, isRequired: boolean = true) => {
645
705
  return isRequired ? schema.required(t('Mount path is required for this volume type')) : schema;
646
706
  };
647
707
 
648
- // Volume validation schemas
649
708
  const singleContainerVolumesSchema = (t: TFunction) =>
650
709
  Yup.array().of(
651
710
  Yup.object().shape({
652
711
  name: volumeNameSchema(t),
653
- imageRef: optionalImageRefSchema(t),
712
+ imageRef: ociImageSchema(t),
654
713
  imagePullPolicy: Yup.string(),
655
714
  mountPath: mountPathSchema(t, true),
656
715
  }),
@@ -660,7 +719,7 @@ const composeQuadletVolumesSchema = (t: TFunction) =>
660
719
  Yup.array().of(
661
720
  Yup.object().shape({
662
721
  name: volumeNameSchema(t),
663
- imageRef: optionalImageRefSchema(t).required(t('Image reference is required for this volume type')),
722
+ imageRef: requiredOciImageSchema(t, t('Image reference is required for this volume type')),
664
723
  imagePullPolicy: imagePullPolicySchema(t),
665
724
  }),
666
725
  );
@@ -670,16 +729,14 @@ export const validApplicationsSchema = (t: TFunction) => {
670
729
  .of(
671
730
  Yup.lazy((value: AppForm) => {
672
731
  // Container applications (image-based with ports and resources)
673
- if (isSingleContainerAppForm(value)) {
732
+ if (value.appType === AppType.AppTypeContainer) {
674
733
  return Yup.object().shape({
675
734
  specType: Yup.string()
676
735
  .oneOf([AppSpecType.OCI_IMAGE])
677
736
  .required(t('Definition source must be image for this type of applications')),
678
737
  appType: Yup.string().oneOf([AppType.AppTypeContainer]).required(t('Application type is required')),
679
- name: validApplicationAndVolumeName(t).required(t('Name is required for single container applications.')),
680
- image: Yup.string()
681
- .required(t('Image is required.'))
682
- .matches(APPLICATION_IMAGE_REGEXP, t('Application image includes invalid characters.')),
738
+ name: validApplicationAndVolumeName(t),
739
+ image: requiredOciImageSchema(t),
683
740
  ports: Yup.array().of(
684
741
  Yup.object()
685
742
  .shape({
@@ -709,17 +766,15 @@ export const validApplicationsSchema = (t: TFunction) => {
709
766
  }
710
767
 
711
768
  // Helm applications
712
- if (isHelmImageAppForm(value)) {
713
- return Yup.object<HelmImageAppForm>().shape({
769
+ if (value.appType === AppType.AppTypeHelm) {
770
+ return Yup.object<HelmAppForm>().shape({
714
771
  specType: Yup.string()
715
772
  .oneOf([AppSpecType.OCI_IMAGE])
716
773
  .required(t('Definition source must be image for this type of applications')),
717
774
  appType: Yup.string().oneOf([AppType.AppTypeHelm]).required(t('Application type is required')),
718
775
  name: validApplicationAndVolumeName(t),
719
- image: Yup.string()
720
- .required(t('Image is required.'))
721
- .matches(APPLICATION_IMAGE_REGEXP, t('Application image includes invalid characters.')),
722
- namespace: Yup.string(),
776
+ image: requiredOciImageSchema(t),
777
+ namespace: validHelmNamespace(t),
723
778
  valuesYaml: Yup.string().test('valid-yaml', t('YAML content is invalid.'), (value) => {
724
779
  if (!value || value.trim() === '') {
725
780
  return true;
@@ -731,16 +786,13 @@ export const validApplicationsSchema = (t: TFunction) => {
731
786
  }
732
787
  return true;
733
788
  }),
734
- // Values files don't need to be validated.
735
- // Since the UX design has the first field added by default, we will ignore all empty values files.
736
- // The user can't add more values files if any is empty (though they can clear existing ones).
737
- valuesFiles: Yup.array().of(Yup.string()),
789
+ valuesFiles: Yup.array().of(validHelmValuesFile(t)),
738
790
  });
739
791
  }
740
792
 
741
793
  // Image applications (Quadlet or Compose)
742
- if (isQuadletImageAppForm(value) || isComposeImageAppForm(value)) {
743
- return Yup.object<QuadletImageAppForm | ComposeImageAppForm>().shape({
794
+ if (value.specType === AppSpecType.OCI_IMAGE) {
795
+ return Yup.object<QuadletAppForm | ComposeAppForm>().shape({
744
796
  specType: Yup.string()
745
797
  .oneOf([AppSpecType.OCI_IMAGE])
746
798
  .required(t('Definition source must be image for this type of applications')),
@@ -748,17 +800,15 @@ export const validApplicationsSchema = (t: TFunction) => {
748
800
  .oneOf([AppType.AppTypeCompose, AppType.AppTypeQuadlet])
749
801
  .required(t('Application type is required')),
750
802
  name: validApplicationAndVolumeName(t),
751
- image: Yup.string()
752
- .required(t('Image is required.'))
753
- .matches(APPLICATION_IMAGE_REGEXP, t('Application image includes invalid characters.')),
803
+ image: requiredOciImageSchema(t),
754
804
  volumes: composeQuadletVolumesSchema(t),
755
805
  variables: appVariablesSchema(t),
756
806
  });
757
807
  }
758
808
 
759
809
  // Inline quadlet applications
760
- if (isQuadletInlineAppForm(value)) {
761
- return Yup.object<QuadletInlineAppForm>().shape({
810
+ if (value.appType === AppType.AppTypeQuadlet && value.specType === AppSpecType.INLINE) {
811
+ return Yup.object<QuadletAppForm>().shape({
762
812
  specType: appSpecTypeSchema(t),
763
813
  appType: Yup.string().oneOf([AppType.AppTypeQuadlet]).required(t('Application type is required')),
764
814
  name: validApplicationAndVolumeName(t).required(t('Name is required for quadlet applications.')),
@@ -772,7 +822,7 @@ export const validApplicationsSchema = (t: TFunction) => {
772
822
  }
773
823
 
774
824
  // Inline compose applications
775
- return Yup.object<ComposeInlineAppForm>().shape({
825
+ return Yup.object<ComposeAppForm>().shape({
776
826
  specType: appSpecTypeSchema(t),
777
827
  appType: Yup.string().oneOf([AppType.AppTypeCompose]).required(t('Application type is required')),
778
828
  name: validApplicationAndVolumeName(t).required(t('Name is required for compose applications.')),
@@ -9,9 +9,10 @@ type CreateRepositoryModalProps = {
9
9
  type: RepoSpecType;
10
10
  onClose: VoidFunction;
11
11
  onSuccess: (repository: Repository) => void;
12
+ validateBeforeCreate?: (repo: Repository) => string | undefined;
12
13
  };
13
14
 
14
- const CreateRepositoryModal = ({ type, onClose, onSuccess }: CreateRepositoryModalProps) => {
15
+ const CreateRepositoryModal = ({ type, onClose, onSuccess, validateBeforeCreate }: CreateRepositoryModalProps) => {
15
16
  const { t } = useTranslation();
16
17
  return (
17
18
  <Modal variant="medium" isOpen>
@@ -20,6 +21,7 @@ const CreateRepositoryModal = ({ type, onClose, onSuccess }: CreateRepositoryMod
20
21
  <CreateRepositoryForm
21
22
  onClose={onClose}
22
23
  onSuccess={onSuccess}
24
+ validateBefore={validateBeforeCreate}
23
25
  options={{
24
26
  canUseResourceSyncs: false,
25
27
  allowedRepoTypes: [type],
package/src/constants.ts CHANGED
@@ -1,7 +1,20 @@
1
- const APP_TITLE = 'Edge Manager';
2
- const API_VERSION = 'v1beta1';
3
- const PAGE_SIZE = 15;
4
- const EVENT_PAGE_SIZE = 200; // It's 500 in OCP console
5
- const CERTIFICATE_VALIDITY_IN_YEARS = 1;
1
+ import { ApiVersion } from '@flightctl/types';
2
+ import { ApiVersion as ImageBuilderApiVersion } from '@flightctl/types/imagebuilder';
6
3
 
7
- export { APP_TITLE, API_VERSION, PAGE_SIZE, EVENT_PAGE_SIZE, CERTIFICATE_VALIDITY_IN_YEARS };
4
+ export const APP_TITLE = 'Edge Manager';
5
+ export const PAGE_SIZE = 15;
6
+ export const EVENT_PAGE_SIZE = 200; // It's 500 in OCP console
7
+
8
+ export const CERTIFICATE_VALIDITY_IN_YEARS = 1;
9
+
10
+ export const getApiVersion = (api: 'flightctl' | 'imagebuilder' | 'alerts'): string | undefined => {
11
+ switch (api) {
12
+ case 'flightctl':
13
+ return ApiVersion.ApiVersionV1beta1;
14
+ case 'imagebuilder':
15
+ return ImageBuilderApiVersion.ApiVersionV1alpha1;
16
+ case 'alerts':
17
+ default:
18
+ return undefined;
19
+ }
20
+ };
@@ -11,6 +11,8 @@ const msgToBytes = (msg: string, resize?: boolean) => {
11
11
  return result;
12
12
  };
13
13
 
14
+ const isErrorCloseEvent = (evt: CloseEvent) => evt.code !== 1000 && evt.code !== 1001;
15
+
14
16
  export type WsMetadata = {
15
17
  tty: boolean;
16
18
  term: string;
@@ -34,13 +36,17 @@ export const useWebSocket = <T>(
34
36
  const { t } = useTranslation();
35
37
  const wsRef = React.useRef<WebSocket>();
36
38
  const isMountedRef = React.useRef(true);
39
+ const hasReceivedMessageRef = React.useRef(false);
37
40
  const [isConnecting, setIsConnecting] = React.useState(true);
38
41
  const [isClosed, setIsClosed] = React.useState(false);
39
42
  const [error, setError] = React.useState<unknown>();
40
43
  const [reset, setReset] = React.useState<number>(0);
41
44
 
42
45
  const sendMessage = React.useCallback((data: string, resize?: boolean) => {
43
- wsRef.current?.send(msgToBytes(data, resize));
46
+ const ws = wsRef.current;
47
+ if (ws?.readyState === WebSocket.OPEN) {
48
+ ws.send(msgToBytes(data, resize));
49
+ }
44
50
  }, []);
45
51
 
46
52
  React.useEffect(() => {
@@ -54,6 +60,8 @@ export const useWebSocket = <T>(
54
60
  try {
55
61
  setIsConnecting(true);
56
62
  setIsClosed(false);
63
+ setError(undefined);
64
+ hasReceivedMessageRef.current = false;
57
65
  const wsEndpoint = getWsEndpoint(deviceId);
58
66
  const wsMeta = JSON.stringify(wsMetadata);
59
67
  const params = new URLSearchParams({
@@ -73,9 +81,16 @@ export const useWebSocket = <T>(
73
81
  }
74
82
  };
75
83
 
76
- const handleClose = () => {
84
+ const handleClose = (evt: CloseEvent) => {
77
85
  if (isMountedRef.current) {
86
+ setIsConnecting(false);
78
87
  setIsClosed(true);
88
+ // If we never received any data from the backend, treat an error close as a failure
89
+ // Otherwise it may be a normal session close, and we'll show the "Reconnect" banner.
90
+ if (isErrorCloseEvent(evt) && !hasReceivedMessageRef.current) {
91
+ const reason = evt.reason || t('Unknown error');
92
+ setError(t('Failed to connect to device terminal: {{reason}}', { reason }));
93
+ }
79
94
  }
80
95
  wsRef.current = undefined;
81
96
  };
@@ -84,7 +99,13 @@ export const useWebSocket = <T>(
84
99
  // eslint-disable-next-line no-console
85
100
  console.error('Error creating websocket:', evt);
86
101
  if (isMountedRef.current) {
87
- setError(t('Websocket error occured'));
102
+ setIsConnecting(false);
103
+ if (!hasReceivedMessageRef.current) {
104
+ setError(t('Failed to connect to device terminal'));
105
+ } else {
106
+ // User may have closed the session, so we'll show the "Reconnect" banner.
107
+ setIsClosed(true);
108
+ }
88
109
  }
89
110
  };
90
111
 
@@ -120,6 +141,7 @@ export const useWebSocket = <T>(
120
141
  React.useEffect(() => {
121
142
  const listener = (evt: MessageEvent<T>) => {
122
143
  if (isMountedRef.current) {
144
+ hasReceivedMessageRef.current = true;
123
145
  onMsgReceived(evt.data);
124
146
  }
125
147
  };