@flightctl/ui-components 0.4.0 → 0.5.0-rc1

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 (384) hide show
  1. package/dist/src/components/DetailsPage/DetailsPageActions.d.ts +11 -4
  2. package/dist/src/components/DetailsPage/DetailsPageActions.d.ts.map +1 -1
  3. package/dist/src/components/DetailsPage/DetailsPageActions.js +15 -4
  4. package/dist/src/components/DetailsPage/DetailsPageActions.js.map +1 -1
  5. package/dist/src/components/DetailsPage/Tables/ApplicationsTable.js +1 -1
  6. package/dist/src/components/DetailsPage/Tables/ApplicationsTable.js.map +1 -1
  7. package/dist/src/components/Device/DeviceDetails/DeviceApplications.d.ts +1 -1
  8. package/dist/src/components/Device/DeviceDetails/DeviceApplications.d.ts.map +1 -1
  9. package/dist/src/components/Device/DeviceDetails/DeviceApplications.js +2 -2
  10. package/dist/src/components/Device/DeviceDetails/DeviceApplications.js.map +1 -1
  11. package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.d.ts.map +1 -1
  12. package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.js +22 -15
  13. package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.js.map +1 -1
  14. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.d.ts.map +1 -1
  15. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.js +42 -39
  16. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.js.map +1 -1
  17. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.d.ts +7 -0
  18. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.d.ts.map +1 -0
  19. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.js +41 -0
  20. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.js.map +1 -0
  21. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.d.ts +7 -0
  22. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.d.ts.map +1 -0
  23. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.js +30 -0
  24. package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.js.map +1 -0
  25. package/dist/src/components/Device/DeviceDetails/TerminalTab.d.ts.map +1 -1
  26. package/dist/src/components/Device/DeviceDetails/TerminalTab.js +1 -1
  27. package/dist/src/components/Device/DeviceDetails/TerminalTab.js.map +1 -1
  28. package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.d.ts +16 -0
  29. package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.d.ts.map +1 -0
  30. package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.js +57 -0
  31. package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.js.map +1 -0
  32. package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.d.ts +16 -0
  33. package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.d.ts.map +1 -0
  34. package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.js +73 -0
  35. package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.js.map +1 -0
  36. package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.d.ts +10 -0
  37. package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.d.ts.map +1 -0
  38. package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.js +19 -0
  39. package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.js.map +1 -0
  40. package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.d.ts +8 -0
  41. package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.d.ts.map +1 -0
  42. package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.js +34 -0
  43. package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.js.map +1 -0
  44. package/dist/src/components/Device/DevicesPage/DevicesPage.d.ts +0 -22
  45. package/dist/src/components/Device/DevicesPage/DevicesPage.d.ts.map +1 -1
  46. package/dist/src/components/Device/DevicesPage/DevicesPage.js +9 -92
  47. package/dist/src/components/Device/DevicesPage/DevicesPage.js.map +1 -1
  48. package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.d.ts +16 -0
  49. package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.d.ts.map +1 -0
  50. package/dist/src/components/Device/DevicesPage/{DeviceTableRow.js → EnrolledDeviceTableRow.js} +9 -13
  51. package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.js.map +1 -0
  52. package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.d.ts +23 -0
  53. package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.d.ts.map +1 -0
  54. package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.js +99 -0
  55. package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.js.map +1 -0
  56. package/dist/src/components/Device/DevicesPage/useDevices.d.ts +2 -0
  57. package/dist/src/components/Device/DevicesPage/useDevices.d.ts.map +1 -1
  58. package/dist/src/components/Device/DevicesPage/useDevices.js +16 -1
  59. package/dist/src/components/Device/DevicesPage/useDevices.js.map +1 -1
  60. package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.d.ts.map +1 -1
  61. package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.js +5 -3
  62. package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.js.map +1 -1
  63. package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.js +1 -1
  64. package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.js.map +1 -1
  65. package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.d.ts.map +1 -1
  66. package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js +2 -2
  67. package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js.map +1 -1
  68. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.d.ts.map +1 -1
  69. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.js +1 -1
  70. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.js.map +1 -1
  71. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.d.ts.map +1 -1
  72. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.js +1 -1
  73. package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.js.map +1 -1
  74. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.d.ts.map +1 -1
  75. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.js +7 -7
  76. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.js.map +1 -1
  77. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.d.ts +9 -0
  78. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.d.ts.map +1 -0
  79. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.js +37 -0
  80. package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.js.map +1 -0
  81. package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.d.ts.map +1 -1
  82. package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.js +6 -4
  83. package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.js.map +1 -1
  84. package/dist/src/components/Device/EditDeviceWizard/utils.d.ts +1 -1
  85. package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.d.ts.map +1 -1
  86. package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.js +4 -13
  87. package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.js.map +1 -1
  88. package/dist/src/components/EnrollmentRequest/EnrollmentRequestList.js +2 -2
  89. package/dist/src/components/EnrollmentRequest/EnrollmentRequestList.js.map +1 -1
  90. package/dist/src/components/EnrollmentRequest/EnrollmentRequestTableRow.d.ts +2 -2
  91. package/dist/src/components/EnrollmentRequest/EnrollmentRequestTableRow.d.ts.map +1 -1
  92. package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.d.ts +2 -2
  93. package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.d.ts.map +1 -1
  94. package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.js.map +1 -1
  95. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.d.ts.map +1 -1
  96. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.js +32 -3
  97. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.js.map +1 -1
  98. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.d.ts.map +1 -1
  99. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.js +4 -0
  100. package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.js.map +1 -1
  101. package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.d.ts +26 -0
  102. package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.d.ts.map +1 -0
  103. package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.js +63 -0
  104. package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.js.map +1 -0
  105. package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.d.ts.map +1 -1
  106. package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.js +19 -10
  107. package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.js.map +1 -1
  108. package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.d.ts +9 -0
  109. package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.d.ts.map +1 -0
  110. package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.js +52 -0
  111. package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.js.map +1 -0
  112. package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.d.ts +8 -0
  113. package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.d.ts.map +1 -0
  114. package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.js +95 -0
  115. package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.js.map +1 -0
  116. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.d.ts +4 -0
  117. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.d.ts.map +1 -0
  118. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.js +32 -0
  119. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.js.map +1 -0
  120. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.d.ts +4 -0
  121. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.d.ts.map +1 -0
  122. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.js +78 -0
  123. package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.js.map +1 -0
  124. package/dist/src/components/Fleet/CreateFleet/types.d.ts +21 -0
  125. package/dist/src/components/Fleet/CreateFleet/types.d.ts.map +1 -1
  126. package/dist/src/components/Fleet/CreateFleet/types.js +6 -0
  127. package/dist/src/components/Fleet/CreateFleet/types.js.map +1 -1
  128. package/dist/src/components/Fleet/CreateFleet/utils.d.ts.map +1 -1
  129. package/dist/src/components/Fleet/CreateFleet/utils.js +15 -1
  130. package/dist/src/components/Fleet/CreateFleet/utils.js.map +1 -1
  131. package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.d.ts.map +1 -1
  132. package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.js +9 -7
  133. package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.js.map +1 -1
  134. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.d.ts +9 -0
  135. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.d.ts.map +1 -0
  136. package/dist/src/components/Fleet/FleetDetails/{FleetDevices.js → FleetDevicesCharts.js} +4 -4
  137. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.js.map +1 -0
  138. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.d.ts +10 -0
  139. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.d.ts.map +1 -0
  140. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.js +30 -0
  141. package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.js.map +1 -0
  142. package/dist/src/components/Fleet/FleetResourceSyncs.js +2 -2
  143. package/dist/src/components/Fleet/FleetResourceSyncs.js.map +1 -1
  144. package/dist/src/components/Fleet/FleetRow.d.ts.map +1 -1
  145. package/dist/src/components/Fleet/FleetRow.js +7 -5
  146. package/dist/src/components/Fleet/FleetRow.js.map +1 -1
  147. package/dist/src/components/Fleet/FleetsPage.js +2 -2
  148. package/dist/src/components/Fleet/FleetsPage.js.map +1 -1
  149. package/dist/src/components/Fleet/useFleets.d.ts +3 -3
  150. package/dist/src/components/Fleet/useFleets.d.ts.map +1 -1
  151. package/dist/src/components/Fleet/useFleets.js +3 -3
  152. package/dist/src/components/Fleet/useFleets.js.map +1 -1
  153. package/dist/src/components/ListPage/ListPage.d.ts.map +1 -1
  154. package/dist/src/components/ListPage/ListPage.js +6 -1
  155. package/dist/src/components/ListPage/ListPage.js.map +1 -1
  156. package/dist/src/components/ListPage/ListPageActions.d.ts +8 -15
  157. package/dist/src/components/ListPage/ListPageActions.d.ts.map +1 -1
  158. package/dist/src/components/ListPage/ListPageActions.js +25 -5
  159. package/dist/src/components/ListPage/ListPageActions.js.map +1 -1
  160. package/dist/src/components/ListPage/types.d.ts +11 -11
  161. package/dist/src/components/ListPage/types.d.ts.map +1 -1
  162. package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.d.ts.map +1 -1
  163. package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.js +0 -1
  164. package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.js.map +1 -1
  165. package/dist/src/components/OverviewPage/OverviewPage.d.ts.map +1 -1
  166. package/dist/src/components/OverviewPage/OverviewPage.js +6 -1
  167. package/dist/src/components/OverviewPage/OverviewPage.js.map +1 -1
  168. package/dist/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.js +1 -1
  169. package/dist/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.js.map +1 -1
  170. package/dist/src/components/Repository/useRepositories.d.ts +2 -2
  171. package/dist/src/components/Repository/useRepositories.d.ts.map +1 -1
  172. package/dist/src/components/Repository/useRepositories.js.map +1 -1
  173. package/dist/src/components/ResourceSync/RepositoryResourceSyncList.js +2 -2
  174. package/dist/src/components/ResourceSync/RepositoryResourceSyncList.js.map +1 -1
  175. package/dist/src/components/Status/DeviceLifecycleStatus.d.ts +7 -0
  176. package/dist/src/components/Status/DeviceLifecycleStatus.d.ts.map +1 -0
  177. package/dist/src/components/Status/DeviceLifecycleStatus.js +25 -0
  178. package/dist/src/components/Status/DeviceLifecycleStatus.js.map +1 -0
  179. package/dist/src/components/Status/StatusDisplay.d.ts +1 -1
  180. package/dist/src/components/Status/StatusDisplay.d.ts.map +1 -1
  181. package/dist/src/components/Status/StatusDisplay.js +3 -3
  182. package/dist/src/components/Status/StatusDisplay.js.map +1 -1
  183. package/dist/src/components/Table/Table.d.ts.map +1 -1
  184. package/dist/src/components/Table/Table.js +2 -2
  185. package/dist/src/components/Table/Table.js.map +1 -1
  186. package/dist/src/components/Table/TablePagination.d.ts +4 -3
  187. package/dist/src/components/Table/TablePagination.d.ts.map +1 -1
  188. package/dist/src/components/Table/TablePagination.js +6 -5
  189. package/dist/src/components/Table/TablePagination.js.map +1 -1
  190. package/dist/src/components/common/EditableLabelControl.d.ts.map +1 -1
  191. package/dist/src/components/common/EditableLabelControl.js +5 -7
  192. package/dist/src/components/common/EditableLabelControl.js.map +1 -1
  193. package/dist/src/components/common/TechPreviewBadge.d.ts +4 -0
  194. package/dist/src/components/common/TechPreviewBadge.d.ts.map +1 -0
  195. package/dist/src/components/common/TechPreviewBadge.js +23 -0
  196. package/dist/src/components/common/TechPreviewBadge.js.map +1 -0
  197. package/dist/src/components/form/LabelsField.d.ts.map +1 -1
  198. package/dist/src/components/form/LabelsField.js +4 -1
  199. package/dist/src/components/form/LabelsField.js.map +1 -1
  200. package/dist/src/components/form/NumberField.d.ts +10 -0
  201. package/dist/src/components/form/NumberField.d.ts.map +1 -0
  202. package/dist/src/components/form/NumberField.js +51 -0
  203. package/dist/src/components/form/NumberField.js.map +1 -0
  204. package/dist/src/components/form/TextListField.d.ts +12 -0
  205. package/dist/src/components/form/TextListField.d.ts.map +1 -0
  206. package/dist/src/components/form/TextListField.js +46 -0
  207. package/dist/src/components/form/TextListField.js.map +1 -0
  208. package/dist/src/components/form/validations.d.ts +34 -6
  209. package/dist/src/components/form/validations.d.ts.map +1 -1
  210. package/dist/src/components/form/validations.js +78 -4
  211. package/dist/src/components/form/validations.js.map +1 -1
  212. package/dist/src/components/modals/DecommissionModal/DecommissionModal.d.ts +9 -0
  213. package/dist/src/components/modals/DecommissionModal/DecommissionModal.d.ts.map +1 -0
  214. package/dist/src/components/modals/DecommissionModal/DecommissionModal.js +51 -0
  215. package/dist/src/components/modals/DecommissionModal/DecommissionModal.js.map +1 -0
  216. package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.d.ts +4 -2
  217. package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.d.ts.map +1 -1
  218. package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.js +11 -4
  219. package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.js.map +1 -1
  220. package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.d.ts +10 -0
  221. package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.d.ts.map +1 -0
  222. package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.js +67 -0
  223. package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.js.map +1 -0
  224. package/dist/src/constants.d.ts +1 -1
  225. package/dist/src/constants.d.ts.map +1 -1
  226. package/dist/src/constants.js +1 -1
  227. package/dist/src/constants.js.map +1 -1
  228. package/dist/src/hooks/useAppContext.d.ts +1 -1
  229. package/dist/src/hooks/useAppContext.d.ts.map +1 -1
  230. package/dist/src/hooks/useFetch.d.ts +1 -1
  231. package/dist/src/hooks/useFetchPeriodically.js +10 -10
  232. package/dist/src/hooks/useFetchPeriodically.js.map +1 -1
  233. package/dist/src/hooks/useTablePagination.d.ts +5 -3
  234. package/dist/src/hooks/useTablePagination.d.ts.map +1 -1
  235. package/dist/src/hooks/useTablePagination.js +9 -5
  236. package/dist/src/hooks/useTablePagination.js.map +1 -1
  237. package/dist/src/hooks/useWebSocket.d.ts +1 -1
  238. package/dist/src/hooks/useWebSocket.js +4 -4
  239. package/dist/src/hooks/useWebSocket.js.map +1 -1
  240. package/dist/src/links.d.ts +1 -0
  241. package/dist/src/links.d.ts.map +1 -1
  242. package/dist/src/links.js +2 -1
  243. package/dist/src/links.js.map +1 -1
  244. package/dist/src/types/rbac.d.ts +3 -1
  245. package/dist/src/types/rbac.d.ts.map +1 -1
  246. package/dist/src/types/rbac.js +2 -0
  247. package/dist/src/types/rbac.js.map +1 -1
  248. package/dist/src/utils/api.d.ts +3 -6
  249. package/dist/src/utils/api.d.ts.map +1 -1
  250. package/dist/src/utils/api.js.map +1 -1
  251. package/dist/src/utils/apiCalls.d.ts +2 -0
  252. package/dist/src/utils/apiCalls.d.ts.map +1 -0
  253. package/dist/src/utils/apiCalls.js +23 -0
  254. package/dist/src/utils/apiCalls.js.map +1 -0
  255. package/dist/src/utils/devices.d.ts +6 -3
  256. package/dist/src/utils/devices.d.ts.map +1 -1
  257. package/dist/src/utils/devices.js +20 -1
  258. package/dist/src/utils/devices.js.map +1 -1
  259. package/dist/src/utils/patch.d.ts +4 -1
  260. package/dist/src/utils/patch.d.ts.map +1 -1
  261. package/dist/src/utils/patch.js +166 -9
  262. package/dist/src/utils/patch.js.map +1 -1
  263. package/dist/src/utils/status/common.js +13 -12
  264. package/dist/src/utils/status/common.js.map +1 -1
  265. package/dist/src/utils/status/devices.d.ts +3 -3
  266. package/dist/src/utils/status/devices.d.ts.map +1 -1
  267. package/dist/src/utils/status/devices.js +40 -5
  268. package/dist/src/utils/status/devices.js.map +1 -1
  269. package/dist/src/utils/status/fleet.d.ts +4 -4
  270. package/dist/src/utils/status/fleet.d.ts.map +1 -1
  271. package/dist/src/utils/status/fleet.js +15 -2
  272. package/dist/src/utils/status/fleet.js.map +1 -1
  273. package/dist/src/utils/tooltip.d.ts +7 -0
  274. package/dist/src/utils/tooltip.d.ts.map +1 -0
  275. package/dist/src/utils/tooltip.js +6 -0
  276. package/dist/src/utils/tooltip.js.map +1 -0
  277. package/package.json +1 -1
  278. package/src/components/DetailsPage/DetailsPageActions.tsx +34 -6
  279. package/src/components/DetailsPage/Tables/ApplicationsTable.tsx +1 -1
  280. package/src/components/Device/DeviceDetails/DeviceApplications.tsx +3 -3
  281. package/src/components/Device/DeviceDetails/DeviceDetailsPage.tsx +53 -34
  282. package/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx +71 -54
  283. package/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.tsx +75 -0
  284. package/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.tsx +47 -0
  285. package/src/components/Device/DeviceDetails/TerminalTab.tsx +1 -4
  286. package/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.tsx +89 -0
  287. package/src/components/Device/DevicesPage/DecommissionedDevicesTable.tsx +156 -0
  288. package/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.tsx +30 -0
  289. package/src/components/Device/DevicesPage/DevicesEmptyStates.tsx +46 -0
  290. package/src/components/Device/DevicesPage/DevicesPage.tsx +45 -215
  291. package/src/components/Device/DevicesPage/{DeviceTableRow.tsx → EnrolledDeviceTableRow.tsx} +16 -20
  292. package/src/components/Device/DevicesPage/EnrolledDevicesTable.tsx +208 -0
  293. package/src/components/Device/DevicesPage/useDevices.ts +21 -1
  294. package/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx +6 -3
  295. package/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.tsx +1 -1
  296. package/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.tsx +2 -0
  297. package/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.tsx +1 -0
  298. package/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.tsx +1 -0
  299. package/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.tsx +27 -19
  300. package/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.tsx +55 -0
  301. package/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.tsx +9 -7
  302. package/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.tsx +10 -36
  303. package/src/components/EnrollmentRequest/EnrollmentRequestList.tsx +2 -2
  304. package/src/components/EnrollmentRequest/EnrollmentRequestTableRow.tsx +2 -2
  305. package/src/components/EnrollmentRequest/useEnrollmentRequests.ts +3 -2
  306. package/src/components/Fleet/CreateFleet/CreateFleetWizard.tsx +46 -5
  307. package/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.tsx +4 -0
  308. package/src/components/Fleet/CreateFleet/fleetSpecUtils.ts +62 -0
  309. package/src/components/Fleet/CreateFleet/steps/ReviewStep.tsx +65 -30
  310. package/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.tsx +87 -0
  311. package/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.tsx +155 -0
  312. package/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.tsx +91 -0
  313. package/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.tsx +190 -0
  314. package/src/components/Fleet/CreateFleet/types.ts +25 -0
  315. package/src/components/Fleet/CreateFleet/utils.ts +20 -1
  316. package/src/components/Fleet/FleetDetails/FleetDetailsContent.tsx +10 -7
  317. package/src/components/Fleet/FleetDetails/{FleetDevices.tsx → FleetDevicesCharts.tsx} +4 -4
  318. package/src/components/Fleet/FleetDetails/FleetDevicesCount.tsx +53 -0
  319. package/src/components/Fleet/FleetResourceSyncs.tsx +2 -2
  320. package/src/components/Fleet/FleetRow.tsx +12 -4
  321. package/src/components/Fleet/FleetsPage.tsx +2 -2
  322. package/src/components/Fleet/useFleets.ts +7 -7
  323. package/src/components/ListPage/ListPage.tsx +12 -4
  324. package/src/components/ListPage/ListPageActions.tsx +50 -16
  325. package/src/components/ListPage/types.ts +8 -8
  326. package/src/components/OverviewPage/Cards/Status/DeviceStatusChart.tsx +0 -1
  327. package/src/components/OverviewPage/OverviewPage.tsx +12 -4
  328. package/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.tsx +1 -1
  329. package/src/components/Repository/useRepositories.ts +2 -2
  330. package/src/components/ResourceSync/RepositoryResourceSyncList.tsx +2 -2
  331. package/src/components/Status/DeviceLifecycleStatus.tsx +33 -0
  332. package/src/components/Status/StatusDisplay.tsx +4 -4
  333. package/src/components/Table/Table.tsx +2 -1
  334. package/src/components/Table/TablePagination.tsx +9 -7
  335. package/src/components/common/EditableLabelControl.tsx +7 -6
  336. package/src/components/common/TechPreviewBadge.tsx +43 -0
  337. package/src/components/form/LabelsField.tsx +4 -1
  338. package/src/components/form/NumberField.tsx +78 -0
  339. package/src/components/form/TextListField.tsx +82 -0
  340. package/src/components/form/validations.ts +103 -10
  341. package/src/components/modals/DecommissionModal/DecommissionModal.tsx +95 -0
  342. package/src/components/modals/EditLabelsModal/EditLabelsForm.tsx +9 -8
  343. package/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.tsx +130 -0
  344. package/src/constants.ts +1 -1
  345. package/src/hooks/useAppContext.tsx +1 -1
  346. package/src/hooks/useFetchPeriodically.ts +11 -11
  347. package/src/hooks/{useTablePagination.tsx → useTablePagination.ts} +13 -7
  348. package/src/hooks/useWebSocket.ts +4 -4
  349. package/src/links.ts +2 -0
  350. package/src/types/rbac.ts +2 -0
  351. package/src/utils/api.ts +13 -6
  352. package/src/utils/apiCalls.ts +15 -0
  353. package/src/utils/devices.ts +21 -3
  354. package/src/utils/patch.ts +182 -8
  355. package/src/utils/status/common.ts +8 -8
  356. package/src/utils/status/devices.ts +39 -8
  357. package/src/utils/status/fleet.ts +21 -6
  358. package/src/utils/tooltip.ts +2 -0
  359. package/dist/src/components/DetailsPage/Tables/IntegrityDetails.d.ts +0 -8
  360. package/dist/src/components/DetailsPage/Tables/IntegrityDetails.d.ts.map +0 -1
  361. package/dist/src/components/DetailsPage/Tables/IntegrityDetails.js +0 -23
  362. package/dist/src/components/DetailsPage/Tables/IntegrityDetails.js.map +0 -1
  363. package/dist/src/components/Device/DevicesPage/DeviceTableRow.d.ts +0 -16
  364. package/dist/src/components/Device/DevicesPage/DeviceTableRow.d.ts.map +0 -1
  365. package/dist/src/components/Device/DevicesPage/DeviceTableRow.js.map +0 -1
  366. package/dist/src/components/Fleet/FleetDetails/FleetDevices.d.ts +0 -9
  367. package/dist/src/components/Fleet/FleetDetails/FleetDevices.d.ts.map +0 -1
  368. package/dist/src/components/Fleet/FleetDetails/FleetDevices.js.map +0 -1
  369. package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.d.ts +0 -7
  370. package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.d.ts.map +0 -1
  371. package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.js +0 -13
  372. package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.js.map +0 -1
  373. package/dist/src/components/Status/IntegrityStatus.d.ts +0 -7
  374. package/dist/src/components/Status/IntegrityStatus.d.ts.map +0 -1
  375. package/dist/src/components/Status/IntegrityStatus.js +0 -17
  376. package/dist/src/components/Status/IntegrityStatus.js.map +0 -1
  377. package/dist/src/utils/status/integrity.d.ts +0 -5
  378. package/dist/src/utils/status/integrity.d.ts.map +0 -1
  379. package/dist/src/utils/status/integrity.js +0 -28
  380. package/dist/src/utils/status/integrity.js.map +0 -1
  381. package/src/components/DetailsPage/Tables/IntegrityDetails.tsx +0 -44
  382. package/src/components/Fleet/FleetDetails/FleetDevicesLink.tsx +0 -16
  383. package/src/components/Status/IntegrityStatus.tsx +0 -19
  384. package/src/utils/status/integrity.ts +0 -26
@@ -0,0 +1,87 @@
1
+ import * as React from 'react';
2
+ import { Button, Modal, Stack, StackItem } from '@patternfly/react-core';
3
+ import { TFunction } from 'react-i18next';
4
+
5
+ import { useTranslation } from '../../../../hooks/useTranslation';
6
+
7
+ export type StepSetting = 'all-settings' | 'rollout-policies' | 'disruption-budget';
8
+
9
+ type UpdateConfirmChangesModalProps = {
10
+ setting: StepSetting;
11
+ onClose: (doSwitch: boolean) => void;
12
+ };
13
+
14
+ const getModalContent = (setting: StepSetting, t: TFunction) => {
15
+ switch (setting) {
16
+ case 'all-settings':
17
+ return {
18
+ title: t('Switch to basic update configuration?'),
19
+ primaryAction: t('Switch to basic configurations'),
20
+ question: t('Are you sure you want to switch to basic update configurations?'),
21
+ result: t('If you confirm, all advanced configurations will be lost.'),
22
+ };
23
+ case 'rollout-policies': {
24
+ const title = t("Don't use rollout policies configurations");
25
+ return {
26
+ title,
27
+ primaryAction: title,
28
+ question: t('Are you sure you want to remove the rollout policies configurations?'),
29
+ result: t('If you confirm, all rollout policies configurations will be lost.'),
30
+ };
31
+ }
32
+
33
+ case 'disruption-budget': {
34
+ const title = t("Don't use disruption budget configurations");
35
+ return {
36
+ title,
37
+ primaryAction: title,
38
+ question: t('Are you sure you want to remove the disruption budget configurations?'),
39
+ result: t('If you confirm, all disruption budget configurations will be lost.'),
40
+ };
41
+ }
42
+ }
43
+ };
44
+
45
+ const UpdateConfirmChangesModal = ({ setting, onClose }: UpdateConfirmChangesModalProps) => {
46
+ const { t } = useTranslation();
47
+
48
+ const modalContentProps = getModalContent(setting, t);
49
+
50
+ return (
51
+ <Modal
52
+ variant={setting === 'disruption-budget' ? 'medium' : 'small'}
53
+ title={modalContentProps.title}
54
+ titleIconVariant="warning"
55
+ isOpen
56
+ >
57
+ <Stack hasGutter>
58
+ <StackItem>{modalContentProps.question}</StackItem>
59
+ <StackItem>{modalContentProps.result}</StackItem>
60
+ <StackItem>
61
+ <Button
62
+ key="confirm"
63
+ variant="primary"
64
+ tabIndex={0}
65
+ onClick={() => {
66
+ onClose(true);
67
+ }}
68
+ >
69
+ {modalContentProps.primaryAction}
70
+ </Button>
71
+ <Button
72
+ key="cancel"
73
+ variant="link"
74
+ tabIndex={0}
75
+ onClick={() => {
76
+ onClose(false);
77
+ }}
78
+ >
79
+ {t('Cancel')}
80
+ </Button>
81
+ </StackItem>
82
+ </Stack>
83
+ </Modal>
84
+ );
85
+ };
86
+
87
+ export default UpdateConfirmChangesModal;
@@ -0,0 +1,155 @@
1
+ import * as React from 'react';
2
+ import { Alert, Checkbox, FormGroup, FormSection, Grid } from '@patternfly/react-core';
3
+ import { FormikErrors, useFormikContext } from 'formik';
4
+
5
+ import { FleetFormValues } from '../types';
6
+ import { DEFAULT_BACKEND_UPDATE_TIMEOUT_MINUTES, getEmptyInitializedBatch } from '../fleetSpecUtils';
7
+ import { useTranslation } from '../../../../hooks/useTranslation';
8
+ import WithHelperText from '../../../common/WithHelperText';
9
+
10
+ import FlightCtlForm from '../../../form/FlightCtlForm';
11
+ import UpdateStepRolloutPolicy from './UpdateStepRolloutPolicy';
12
+ import UpdateStepDisruptionBudget from './UpdateStepDisruptionBudget';
13
+ import UpdateConfirmChangesModal, { StepSetting } from './UpdateConfirmChangesModal';
14
+
15
+ export const updatePolicyStepId = 'update-policy';
16
+
17
+ export const isUpdatePolicyStepValid = (errors: FormikErrors<FleetFormValues>) =>
18
+ !errors.rolloutPolicy && !errors.disruptionBudget;
19
+
20
+ const UpdatePolicyStep = () => {
21
+ const { t } = useTranslation();
22
+
23
+ const {
24
+ values: { rolloutPolicy, disruptionBudget },
25
+ setFieldValue,
26
+ } = useFormikContext<FleetFormValues>();
27
+
28
+ const [forceShowAdvancedMode, setForceShowAdvancedMode] = React.useState<boolean>(false);
29
+ const [alertSwitchToBasic, setAlertSwitchToBasic] = React.useState<StepSetting>();
30
+ const hasAdvancedMode = rolloutPolicy.isAdvanced || disruptionBudget.isAdvanced;
31
+
32
+ const onSettingsChange = (setting: StepSetting, toAdvanced: boolean) => {
33
+ if (toAdvanced) {
34
+ switch (setting) {
35
+ case 'all-settings':
36
+ setForceShowAdvancedMode(true);
37
+ break;
38
+ case 'rollout-policies':
39
+ setFieldValue('rolloutPolicy.isAdvanced', true);
40
+ onChangePolicyType(true);
41
+ break;
42
+ case 'disruption-budget':
43
+ setFieldValue('disruptionBudget.isAdvanced', true);
44
+ onChangeDisruptionBudget(true);
45
+ break;
46
+ }
47
+ } else {
48
+ setAlertSwitchToBasic(setting);
49
+ }
50
+ };
51
+
52
+ const onChangePolicyType = async (toAdvanced: boolean) => {
53
+ await setFieldValue('rolloutPolicy', {
54
+ isAdvanced: toAdvanced,
55
+ batches: toAdvanced ? [getEmptyInitializedBatch()] : [],
56
+ updateTimeout: DEFAULT_BACKEND_UPDATE_TIMEOUT_MINUTES,
57
+ });
58
+ };
59
+
60
+ const onChangeDisruptionBudget = async (toAdvanced: boolean) => {
61
+ if (!toAdvanced) {
62
+ await setFieldValue('disruptionBudget', {
63
+ isAdvanced: false,
64
+ groupBy: [],
65
+ minAvailable: '',
66
+ maxUnavailable: '',
67
+ });
68
+ }
69
+ };
70
+
71
+ const onModalClose = async (doSwitch: boolean) => {
72
+ setAlertSwitchToBasic(undefined);
73
+ if (!doSwitch) {
74
+ return;
75
+ }
76
+
77
+ // When the user confirms switching a setting to its basic mode
78
+ switch (alertSwitchToBasic) {
79
+ case 'all-settings':
80
+ await onChangePolicyType(false);
81
+ await onChangeDisruptionBudget(false);
82
+ break;
83
+ case 'rollout-policies':
84
+ void onChangePolicyType(false);
85
+ break;
86
+ case 'disruption-budget':
87
+ void onChangeDisruptionBudget(false);
88
+ break;
89
+ }
90
+ setForceShowAdvancedMode(false);
91
+ };
92
+
93
+ return (
94
+ <Grid span={8}>
95
+ <FlightCtlForm>
96
+ <FormGroup>
97
+ <Checkbox
98
+ label={t('Use basic configurations')}
99
+ isChecked={!hasAdvancedMode && !forceShowAdvancedMode}
100
+ id="all-settings"
101
+ onChange={(_ev: React.FormEvent<HTMLInputElement>, toBasic: boolean) => {
102
+ onSettingsChange('all-settings', !toBasic);
103
+ }}
104
+ />
105
+ </FormGroup>
106
+ {hasAdvancedMode || forceShowAdvancedMode ? (
107
+ <FormSection title={t('Advanced configurations')} titleElement="h1" className="pf-v5-u-mt-sm">
108
+ {/* Rollout policies */}
109
+ <Checkbox
110
+ label={
111
+ <WithHelperText
112
+ showLabel
113
+ ariaLabel={t('Set rollout policies')}
114
+ content={t('Rollout policies allow you to control the order of updates for the fleet devices.')}
115
+ />
116
+ }
117
+ isChecked={rolloutPolicy.isAdvanced}
118
+ id="advRolloutPolicy"
119
+ onChange={(_ev: React.FormEvent<HTMLInputElement>, toAdvanced: boolean) =>
120
+ onSettingsChange('rollout-policies', toAdvanced)
121
+ }
122
+ />
123
+ {rolloutPolicy.isAdvanced && <UpdateStepRolloutPolicy />}
124
+
125
+ {/* Disruption budget */}
126
+ <Checkbox
127
+ label={
128
+ <WithHelperText
129
+ showLabel
130
+ ariaLabel={t('Set disruption budget')}
131
+ content={t(
132
+ 'Disruption budget allows you to limit the number of similar devices that may be updating simultaneously.',
133
+ )}
134
+ />
135
+ }
136
+ isChecked={disruptionBudget.isAdvanced}
137
+ id="advDisruptionBudget"
138
+ onChange={(_ev: React.FormEvent<HTMLInputElement>, toAdvanced: boolean) =>
139
+ onSettingsChange('disruption-budget', toAdvanced)
140
+ }
141
+ />
142
+ {disruptionBudget.isAdvanced && <UpdateStepDisruptionBudget />}
143
+ </FormSection>
144
+ ) : (
145
+ <Alert isInline variant="info" title={t('Default update policy')}>
146
+ {t('All the devices that are part of this fleet will receive updates as soon as they are available.')}
147
+ </Alert>
148
+ )}
149
+ {alertSwitchToBasic && <UpdateConfirmChangesModal setting={alertSwitchToBasic} onClose={onModalClose} />}
150
+ </FlightCtlForm>
151
+ </Grid>
152
+ );
153
+ };
154
+
155
+ export default UpdatePolicyStep;
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { useField } from 'formik';
3
+ import { FormGroup, Grid, GridItem, Stack, StackItem } from '@patternfly/react-core';
4
+
5
+ import { useTranslation } from '../../../../hooks/useTranslation';
6
+ import NumberField from '../../../form/NumberField';
7
+ import TextListField from '../../../form/TextListField';
8
+ import ErrorHelperText from '../../../form/FieldHelperText';
9
+ import WithHelperText from '../../../common/WithHelperText';
10
+ import { DisruptionBudgetForm } from '../types';
11
+
12
+ const UpdateStepDisruptionBudget = () => {
13
+ const { t } = useTranslation();
14
+
15
+ const [, meta] = useField<DisruptionBudgetForm>('disruptionBudget');
16
+
17
+ return (
18
+ <Grid hasGutter>
19
+ <FormGroup
20
+ label={
21
+ <WithHelperText
22
+ ariaLabel={t('Group devices by label keys')}
23
+ content={t('The disruption budget will be applied to all group combinations independently.')}
24
+ showLabel
25
+ />
26
+ }
27
+ >
28
+ <TextListField
29
+ name="disruptionBudget.groupBy"
30
+ addButtonText={t('Add label key')}
31
+ helperText={
32
+ <Stack>
33
+ <StackItem>{t("Use only the 'key' part of the labels to group same values.")}</StackItem>
34
+ <StackItem>{t("Leaving this empty will apply the disruption budget to all fleet's devices.")}</StackItem>
35
+ </Stack>
36
+ }
37
+ />
38
+ </FormGroup>
39
+ <FormGroup>
40
+ <Grid hasGutter>
41
+ <GridItem md={6}>
42
+ <FormGroup
43
+ label={
44
+ <WithHelperText
45
+ ariaLabel={t('Minimum number of available devices')}
46
+ content={t(
47
+ 'At least this number of devices will be available at any given moment, for each group defined above.',
48
+ )}
49
+ showLabel
50
+ />
51
+ }
52
+ >
53
+ <NumberField
54
+ aria-label={t('Minimum number of available devices')}
55
+ name="disruptionBudget.minAvailable"
56
+ min={1}
57
+ />
58
+ </FormGroup>
59
+ </GridItem>
60
+ <GridItem md={6}>
61
+ <FormGroup
62
+ label={
63
+ <WithHelperText
64
+ ariaLabel={t('Maximum number of unavailable devices')}
65
+ content={t(
66
+ 'No more than this number of devices will be unavailable at any given moment, for each group defined above.',
67
+ )}
68
+ showLabel
69
+ />
70
+ }
71
+ >
72
+ <NumberField
73
+ aria-label={t('Maximum number of unavailable devices')}
74
+ name="disruptionBudget.maxUnavailable"
75
+ min={1}
76
+ />
77
+ </FormGroup>
78
+ </GridItem>
79
+ {/* Show error when both numberic values are unset */}
80
+ {typeof meta.error === 'string' && (
81
+ <GridItem md={12}>
82
+ <ErrorHelperText meta={meta} />
83
+ </GridItem>
84
+ )}
85
+ </Grid>
86
+ </FormGroup>
87
+ </Grid>
88
+ );
89
+ };
90
+
91
+ export default UpdateStepDisruptionBudget;
@@ -0,0 +1,190 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Alert,
4
+ Button,
5
+ Flex,
6
+ FlexItem,
7
+ FormGroup,
8
+ FormSection,
9
+ Grid,
10
+ GridItem,
11
+ Split,
12
+ SplitItem,
13
+ } from '@patternfly/react-core';
14
+ import { FieldArray, useField, useFormikContext } from 'formik';
15
+ import { MinusCircleIcon, PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons';
16
+
17
+ import { BatchForm, BatchLimitType, FleetFormValues } from '../types';
18
+ import ErrorHelperText from '../../../form/FieldHelperText';
19
+ import ExpandableFormSection from '../../../form/ExpandableFormSection';
20
+ import LabelsField from '../../../form/LabelsField';
21
+ import FormSelect from '../../../form/FormSelect';
22
+ import NumberField from '../../../form/NumberField';
23
+ import WithHelperText from '../../../common/WithHelperText';
24
+ import { useTranslation } from '../../../../hooks/useTranslation';
25
+ import { getEmptyInitializedBatch } from '../fleetSpecUtils';
26
+
27
+ const RolloutPolicyBatch = ({ index }: { index: number }) => {
28
+ const { t } = useTranslation();
29
+
30
+ const items = React.useMemo(
31
+ () => ({
32
+ percent: t('Percentage'),
33
+ value: t('Number of devices'),
34
+ }),
35
+ [t],
36
+ );
37
+
38
+ const [{ value: batch }, meta] = useField<BatchForm>(`rolloutPolicy.batches.${index}`);
39
+
40
+ const isPercent = batch.limitType === BatchLimitType.BatchLimitPercent;
41
+ return (
42
+ <ExpandableFormSection
43
+ title={t('Batch {{ batchNum }}', { batchNum: index + 1 })}
44
+ fieldName={`rolloutPolicy.batches.${index}`}
45
+ >
46
+ <Grid hasGutter>
47
+ {/* Show errors not related to an individual field */}
48
+ {typeof meta.error === 'string' && (
49
+ <GridItem>
50
+ <ErrorHelperText meta={meta} />
51
+ </GridItem>
52
+ )}
53
+ <FormGroup label={t('Select devices using labels')}>
54
+ <LabelsField aria-label={t('Label selector')} name={`rolloutPolicy.batches.${index}.selector`} />
55
+ </FormGroup>
56
+ <FormGroup label={t('Select a subset using')}>
57
+ <Split hasGutter>
58
+ <SplitItem>
59
+ <FormSelect items={items} name={`rolloutPolicy.batches.${index}.limitType`} />
60
+ </SplitItem>
61
+ <SplitItem>
62
+ <NumberField
63
+ aria-label={t('Numeric selector')}
64
+ name={`rolloutPolicy.batches.${index}.limit`}
65
+ min={1}
66
+ max={isPercent ? 100 : undefined}
67
+ widthChars={isPercent ? 3 : 8}
68
+ unit={isPercent ? '%' : undefined}
69
+ />
70
+ </SplitItem>
71
+ </Split>
72
+ </FormGroup>
73
+ <FormGroup
74
+ isRequired
75
+ label={
76
+ <WithHelperText
77
+ ariaLabel={t('Success threshold')}
78
+ content={t(
79
+ 'The minimum percentage of devices that must be updated successfully in order to continue updating the next batch of devices.',
80
+ )}
81
+ showLabel
82
+ />
83
+ }
84
+ >
85
+ <Flex flexWrap={{ default: 'wrap' }}>
86
+ <FlexItem>{t('If')} </FlexItem>
87
+ <FlexItem>
88
+ <NumberField
89
+ aria-label={t('Success threshold')}
90
+ name={`rolloutPolicy.batches.${index}.successThreshold`}
91
+ min={1}
92
+ max={100}
93
+ isRequired
94
+ />
95
+ </FlexItem>
96
+ <FlexItem flex={{ lg: 'flex_1' }} style={{ minWidth: 200 }}>
97
+ {t(
98
+ "% of the batch devices pass the success threshold, move to next batch or the rest of fleet's devices.",
99
+ )}
100
+ </FlexItem>
101
+ </Flex>
102
+ </FormGroup>
103
+ </Grid>
104
+ </ExpandableFormSection>
105
+ );
106
+ };
107
+
108
+ const UpdateStepRolloutPolicy = () => {
109
+ const { t } = useTranslation();
110
+
111
+ const {
112
+ values: { rolloutPolicy },
113
+ } = useFormikContext<FleetFormValues>();
114
+
115
+ const batches = rolloutPolicy.batches || [];
116
+
117
+ return (
118
+ <>
119
+ <Alert isInline variant="info" title={t('Batch sequencing')}>
120
+ {t('Batches will be applied from first to last.')}
121
+ <br />
122
+ {t('Devices that are not part of any batch will be updated last.')}
123
+ </Alert>
124
+ <FormGroup
125
+ isRequired
126
+ label={
127
+ <WithHelperText
128
+ ariaLabel={t('Update timeout')}
129
+ content={t(
130
+ "The time-frame within which a device must be updated. If it exceeds it, device will be counted as a 'failed to update' in the batch success threshold.",
131
+ )}
132
+ showLabel
133
+ />
134
+ }
135
+ >
136
+ <Flex>
137
+ <FlexItem>{t('Timeout devices that fail to update after')}</FlexItem>
138
+ <FlexItem>
139
+ <NumberField aria-label={t('Update timeout')} name="rolloutPolicy.updateTimeout" min={1} isRequired />
140
+ </FlexItem>
141
+ <FlexItem>{t('minutes')}.</FlexItem>
142
+ </Flex>
143
+ </FormGroup>
144
+
145
+ <FormGroup>
146
+ <FieldArray name="rolloutPolicy.batches">
147
+ {({ push, remove }) => (
148
+ <>
149
+ {batches.map((_, index) => (
150
+ <FormSection key={index}>
151
+ <Split hasGutter>
152
+ <SplitItem isFilled>
153
+ <RolloutPolicyBatch index={index} />
154
+ </SplitItem>
155
+ <SplitItem>
156
+ <Button
157
+ aria-label={t('Delete batch')}
158
+ variant="link"
159
+ icon={<MinusCircleIcon />}
160
+ iconPosition="start"
161
+ onClick={() => remove(index)}
162
+ isDisabled={batches.length === 1}
163
+ />
164
+ </SplitItem>
165
+ </Split>
166
+ </FormSection>
167
+ ))}
168
+ <FormSection>
169
+ <FormGroup>
170
+ <Button
171
+ variant="link"
172
+ icon={<PlusCircleIcon />}
173
+ iconPosition="start"
174
+ onClick={() => {
175
+ push(getEmptyInitializedBatch());
176
+ }}
177
+ >
178
+ {t('Add batch')}
179
+ </Button>
180
+ </FormGroup>
181
+ </FormSection>
182
+ </>
183
+ )}
184
+ </FieldArray>
185
+ </FormGroup>
186
+ </>
187
+ );
188
+ };
189
+
190
+ export default UpdateStepRolloutPolicy;
@@ -1,8 +1,33 @@
1
+ import { DisruptionBudget } from '@flightctl/types';
1
2
  import { FlightCtlLabel } from '../../../types/extraTypes';
2
3
  import { DeviceSpecConfigFormValues } from '../../Device/EditDeviceWizard/types';
3
4
 
5
+ export enum BatchLimitType {
6
+ BatchLimitPercent = 'percent',
7
+ BatchLimitAbsoluteNumber = 'value',
8
+ }
9
+
10
+ export type BatchForm = {
11
+ selector: FlightCtlLabel[];
12
+ limit?: number;
13
+ limitType: BatchLimitType;
14
+ successThreshold?: number;
15
+ };
16
+
17
+ export type RolloutPolicyForm = {
18
+ isAdvanced: boolean;
19
+ updateTimeout: number;
20
+ batches: BatchForm[];
21
+ };
22
+
23
+ export type DisruptionBudgetForm = DisruptionBudget & {
24
+ isAdvanced: boolean;
25
+ };
26
+
4
27
  export type FleetFormValues = DeviceSpecConfigFormValues & {
5
28
  name: string;
6
29
  fleetLabels: FlightCtlLabel[];
7
30
  labels: FlightCtlLabel[];
31
+ rolloutPolicy: RolloutPolicyForm;
32
+ disruptionBudget: DisruptionBudgetForm;
8
33
  };
@@ -8,6 +8,8 @@ import {
8
8
  systemdUnitListValidationSchema,
9
9
  validApplicationsSchema,
10
10
  validConfigTemplatesSchema,
11
+ validFleetDisruptionBudgetSchema,
12
+ validFleetRolloutPolicySchema,
11
13
  validKubernetesDnsSubdomain,
12
14
  validLabelsSchema,
13
15
  validOsImage,
@@ -16,6 +18,8 @@ import {
16
18
  appendJSONPatch,
17
19
  getApplicationPatches,
18
20
  getLabelPatches,
21
+ getRolloutPolicyData,
22
+ getRolloutPolicyPatches,
19
23
  getStringListPatches,
20
24
  toAPIApplication,
21
25
  } from '../../../utils/patch';
@@ -29,6 +33,7 @@ import {
29
33
  getDeviceSpecConfigPatches,
30
34
  hasMicroshiftRegistrationConfig,
31
35
  } from '../../Device/EditDeviceWizard/deviceSpecUtils';
36
+ import { getDisruptionBudgetValues, getRolloutPolicyValues } from './fleetSpecUtils';
32
37
 
33
38
  export const getValidationSchema = (t: TFunction) => {
34
39
  return Yup.object<FleetFormValues>({
@@ -39,6 +44,8 @@ export const getValidationSchema = (t: TFunction) => {
39
44
  configTemplates: validConfigTemplatesSchema(t),
40
45
  applications: validApplicationsSchema(t),
41
46
  systemdUnits: systemdUnitListValidationSchema(t),
47
+ rolloutPolicy: validFleetRolloutPolicySchema(t),
48
+ disruptionBudget: validFleetDisruptionBudgetSchema(t),
42
49
  });
43
50
  };
44
51
 
@@ -56,6 +63,7 @@ export const getFleetPatches = (currentFleet: Fleet, updatedFleet: FleetFormValu
56
63
  const currentDeviceSelectLabels = currentFleet.spec.selector?.matchLabels || {};
57
64
  const updatedDeviceSelectLabels = updatedFleet.labels || {};
58
65
  const updatedDeviceSelectLabelCount = Object.keys(updatedDeviceSelectLabels).length;
66
+ const currentDeviceSelectLabelCount = Object.keys(currentDeviceSelectLabels).length;
59
67
 
60
68
  if (updatedDeviceSelectLabelCount > 0) {
61
69
  if (currentFleet.spec.selector) {
@@ -73,7 +81,7 @@ export const getFleetPatches = (currentFleet: Fleet, updatedFleet: FleetFormValu
73
81
  value: { matchLabels: newLabelMap },
74
82
  });
75
83
  }
76
- } else if (currentFleet.spec.selector) {
84
+ } else if (currentDeviceSelectLabelCount > 0) {
77
85
  allPatches.push({
78
86
  path: '/spec/selector',
79
87
  op: 'remove',
@@ -129,6 +137,10 @@ export const getFleetPatches = (currentFleet: Fleet, updatedFleet: FleetFormValu
129
137
  );
130
138
  allPatches = allPatches.concat(unitPatches);
131
139
 
140
+ // Rollout policies (includes disruption budget)
141
+ const rolloutPolicyPatches = getRolloutPolicyPatches(currentFleet.spec.rolloutPolicy, updatedFleet);
142
+ allPatches = allPatches.concat(rolloutPolicyPatches);
143
+
132
144
  return allPatches;
133
145
  };
134
146
 
@@ -171,6 +183,9 @@ export const getFleetResource = (values: FleetFormValues): Fleet => {
171
183
  if (values.registerMicroShift) {
172
184
  fleet.spec.template.spec.config?.push(ACMCrdConfig, ACMImportConfig, MicroshiftRegistrationHook);
173
185
  }
186
+ if (values.rolloutPolicy.isAdvanced || values.disruptionBudget.isAdvanced) {
187
+ fleet.spec.rolloutPolicy = getRolloutPolicyData(values);
188
+ }
174
189
 
175
190
  return fleet;
176
191
  };
@@ -196,6 +211,8 @@ export const getInitialValues = (fleet?: Fleet): FleetFormValues => {
196
211
  exists: true,
197
212
  })),
198
213
  registerMicroShift,
214
+ rolloutPolicy: getRolloutPolicyValues(fleet.spec),
215
+ disruptionBudget: getDisruptionBudgetValues(fleet.spec),
199
216
  };
200
217
  }
201
218
 
@@ -208,5 +225,7 @@ export const getInitialValues = (fleet?: Fleet): FleetFormValues => {
208
225
  applications: [],
209
226
  systemdUnits: [],
210
227
  registerMicroShift: false,
228
+ rolloutPolicy: getRolloutPolicyValues(undefined),
229
+ disruptionBudget: getDisruptionBudgetValues(undefined),
211
230
  };
212
231
  };
@@ -12,20 +12,23 @@ import {
12
12
  } from '@patternfly/react-core';
13
13
 
14
14
  import { Fleet } from '@flightctl/types';
15
- import FleetOwnerLink from './FleetOwnerLink';
16
- import FleetDevices from './FleetDevices';
17
- import FleetStatus from '../FleetStatus';
18
- import FleetDevicesLink from './FleetDevicesLink';
19
15
  import FlightControlDescriptionList from '../../common/FlightCtlDescriptionList';
20
16
  import LabelsView from '../../common/LabelsView';
21
17
  import { getDateDisplay } from '../../../utils/dates';
18
+ import { getFleetRolloutStatusWarning } from '../../../utils/status/fleet';
22
19
  import { useTranslation } from '../../../hooks/useTranslation';
23
20
  import RepositorySourceList from '../../Repository/RepositoryDetails/RepositorySourceList';
21
+ import FleetOwnerLink from './FleetOwnerLink';
22
+ import FleetDevicesCharts from './FleetDevicesCharts';
23
+ import FleetStatus from '../FleetStatus';
24
+ import FleetDevicesCount from './FleetDevicesCount';
24
25
 
25
26
  const FleetDetailsContent = ({ fleet }: { fleet: Fleet }) => {
26
27
  const { t } = useTranslation();
27
28
  const fleetId = fleet.metadata.name as string;
28
29
  const devicesSummary = fleet.status?.devicesSummary;
30
+ const rolloutError = getFleetRolloutStatusWarning(fleet, t);
31
+
29
32
  return (
30
33
  <Grid hasGutter>
31
34
  <GridItem md={12}>
@@ -56,9 +59,9 @@ const FleetDetailsContent = ({ fleet }: { fleet: Fleet }) => {
56
59
  </DescriptionListDescription>
57
60
  </DescriptionListGroup>
58
61
  <DescriptionListGroup>
59
- <DescriptionListTerm>{t('Associated devices')}</DescriptionListTerm>
62
+ <DescriptionListTerm>{t('Up-to-date/devices')}</DescriptionListTerm>
60
63
  <DescriptionListDescription>
61
- <FleetDevicesLink fleetId={fleetId} count={devicesSummary?.total} />
64
+ <FleetDevicesCount fleetId={fleetId} devicesSummary={devicesSummary} error={rolloutError} />
62
65
  </DescriptionListDescription>
63
66
  </DescriptionListGroup>
64
67
  <DescriptionListGroup>
@@ -85,7 +88,7 @@ const FleetDetailsContent = ({ fleet }: { fleet: Fleet }) => {
85
88
  <CardTitle>{t('Fleet devices')}</CardTitle>
86
89
 
87
90
  <CardBody>
88
- <FleetDevices fleetId={fleetId} devicesSummary={devicesSummary} />
91
+ <FleetDevicesCharts fleetId={fleetId} devicesSummary={devicesSummary} />
89
92
  </CardBody>
90
93
  </Card>
91
94
  </GridItem>