@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.
- package/dist/src/components/DetailsPage/DetailsPageActions.d.ts +11 -4
- package/dist/src/components/DetailsPage/DetailsPageActions.d.ts.map +1 -1
- package/dist/src/components/DetailsPage/DetailsPageActions.js +15 -4
- package/dist/src/components/DetailsPage/DetailsPageActions.js.map +1 -1
- package/dist/src/components/DetailsPage/Tables/ApplicationsTable.js +1 -1
- package/dist/src/components/DetailsPage/Tables/ApplicationsTable.js.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceApplications.d.ts +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceApplications.d.ts.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceApplications.js +2 -2
- package/dist/src/components/Device/DeviceDetails/DeviceApplications.js.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.d.ts.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.js +22 -15
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsPage.js.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.d.ts.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.js +42 -39
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTab.js.map +1 -1
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.d.ts +7 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.d.ts.map +1 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.js +41 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.js.map +1 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.d.ts +7 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.d.ts.map +1 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.js +30 -0
- package/dist/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.js.map +1 -0
- package/dist/src/components/Device/DeviceDetails/TerminalTab.d.ts.map +1 -1
- package/dist/src/components/Device/DeviceDetails/TerminalTab.js +1 -1
- package/dist/src/components/Device/DeviceDetails/TerminalTab.js.map +1 -1
- package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.d.ts +16 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.js +57 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.d.ts +16 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.js +73 -0
- package/dist/src/components/Device/DevicesPage/DecommissionedDevicesTable.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.d.ts +10 -0
- package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.js +19 -0
- package/dist/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.d.ts +8 -0
- package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.js +34 -0
- package/dist/src/components/Device/DevicesPage/DevicesEmptyStates.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/DevicesPage.d.ts +0 -22
- package/dist/src/components/Device/DevicesPage/DevicesPage.d.ts.map +1 -1
- package/dist/src/components/Device/DevicesPage/DevicesPage.js +9 -92
- package/dist/src/components/Device/DevicesPage/DevicesPage.js.map +1 -1
- package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.d.ts +16 -0
- package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/{DeviceTableRow.js → EnrolledDeviceTableRow.js} +9 -13
- package/dist/src/components/Device/DevicesPage/EnrolledDeviceTableRow.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.d.ts +23 -0
- package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.d.ts.map +1 -0
- package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.js +99 -0
- package/dist/src/components/Device/DevicesPage/EnrolledDevicesTable.js.map +1 -0
- package/dist/src/components/Device/DevicesPage/useDevices.d.ts +2 -0
- package/dist/src/components/Device/DevicesPage/useDevices.d.ts.map +1 -1
- package/dist/src/components/Device/DevicesPage/useDevices.js +16 -1
- package/dist/src/components/Device/DevicesPage/useDevices.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.js +5 -3
- package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizard.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.js +1 -1
- package/dist/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js +2 -2
- package/dist/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.js +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.js +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.js +7 -7
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.d.ts +9 -0
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.d.ts.map +1 -0
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.js +37 -0
- package/dist/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.js.map +1 -0
- package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.d.ts.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.js +6 -4
- package/dist/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.js.map +1 -1
- package/dist/src/components/Device/EditDeviceWizard/utils.d.ts +1 -1
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.d.ts.map +1 -1
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.js +4 -13
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.js.map +1 -1
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestList.js +2 -2
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestList.js.map +1 -1
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestTableRow.d.ts +2 -2
- package/dist/src/components/EnrollmentRequest/EnrollmentRequestTableRow.d.ts.map +1 -1
- package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.d.ts +2 -2
- package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.d.ts.map +1 -1
- package/dist/src/components/EnrollmentRequest/useEnrollmentRequests.js.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.d.ts.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.js +32 -3
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizard.js.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.d.ts.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.js +4 -0
- package/dist/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.js.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.d.ts +26 -0
- package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.d.ts.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.js +63 -0
- package/dist/src/components/Fleet/CreateFleet/fleetSpecUtils.js.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.d.ts.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.js +19 -10
- package/dist/src/components/Fleet/CreateFleet/steps/ReviewStep.js.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.d.ts +9 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.d.ts.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.js +52 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.js.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.d.ts +8 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.d.ts.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.js +95 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.js.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.d.ts +4 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.d.ts.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.js +32 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.js.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.d.ts +4 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.d.ts.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.js +78 -0
- package/dist/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.js.map +1 -0
- package/dist/src/components/Fleet/CreateFleet/types.d.ts +21 -0
- package/dist/src/components/Fleet/CreateFleet/types.d.ts.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/types.js +6 -0
- package/dist/src/components/Fleet/CreateFleet/types.js.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/utils.d.ts.map +1 -1
- package/dist/src/components/Fleet/CreateFleet/utils.js +15 -1
- package/dist/src/components/Fleet/CreateFleet/utils.js.map +1 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.d.ts.map +1 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.js +9 -7
- package/dist/src/components/Fleet/FleetDetails/FleetDetailsContent.js.map +1 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.d.ts +9 -0
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.d.ts.map +1 -0
- package/dist/src/components/Fleet/FleetDetails/{FleetDevices.js → FleetDevicesCharts.js} +4 -4
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCharts.js.map +1 -0
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.d.ts +10 -0
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.d.ts.map +1 -0
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.js +30 -0
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesCount.js.map +1 -0
- package/dist/src/components/Fleet/FleetResourceSyncs.js +2 -2
- package/dist/src/components/Fleet/FleetResourceSyncs.js.map +1 -1
- package/dist/src/components/Fleet/FleetRow.d.ts.map +1 -1
- package/dist/src/components/Fleet/FleetRow.js +7 -5
- package/dist/src/components/Fleet/FleetRow.js.map +1 -1
- package/dist/src/components/Fleet/FleetsPage.js +2 -2
- package/dist/src/components/Fleet/FleetsPage.js.map +1 -1
- package/dist/src/components/Fleet/useFleets.d.ts +3 -3
- package/dist/src/components/Fleet/useFleets.d.ts.map +1 -1
- package/dist/src/components/Fleet/useFleets.js +3 -3
- package/dist/src/components/Fleet/useFleets.js.map +1 -1
- package/dist/src/components/ListPage/ListPage.d.ts.map +1 -1
- package/dist/src/components/ListPage/ListPage.js +6 -1
- package/dist/src/components/ListPage/ListPage.js.map +1 -1
- package/dist/src/components/ListPage/ListPageActions.d.ts +8 -15
- package/dist/src/components/ListPage/ListPageActions.d.ts.map +1 -1
- package/dist/src/components/ListPage/ListPageActions.js +25 -5
- package/dist/src/components/ListPage/ListPageActions.js.map +1 -1
- package/dist/src/components/ListPage/types.d.ts +11 -11
- package/dist/src/components/ListPage/types.d.ts.map +1 -1
- package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.d.ts.map +1 -1
- package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.js +0 -1
- package/dist/src/components/OverviewPage/Cards/Status/DeviceStatusChart.js.map +1 -1
- package/dist/src/components/OverviewPage/OverviewPage.d.ts.map +1 -1
- package/dist/src/components/OverviewPage/OverviewPage.js +6 -1
- package/dist/src/components/OverviewPage/OverviewPage.js.map +1 -1
- package/dist/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.js +1 -1
- package/dist/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.js.map +1 -1
- package/dist/src/components/Repository/useRepositories.d.ts +2 -2
- package/dist/src/components/Repository/useRepositories.d.ts.map +1 -1
- package/dist/src/components/Repository/useRepositories.js.map +1 -1
- package/dist/src/components/ResourceSync/RepositoryResourceSyncList.js +2 -2
- package/dist/src/components/ResourceSync/RepositoryResourceSyncList.js.map +1 -1
- package/dist/src/components/Status/DeviceLifecycleStatus.d.ts +7 -0
- package/dist/src/components/Status/DeviceLifecycleStatus.d.ts.map +1 -0
- package/dist/src/components/Status/DeviceLifecycleStatus.js +25 -0
- package/dist/src/components/Status/DeviceLifecycleStatus.js.map +1 -0
- package/dist/src/components/Status/StatusDisplay.d.ts +1 -1
- package/dist/src/components/Status/StatusDisplay.d.ts.map +1 -1
- package/dist/src/components/Status/StatusDisplay.js +3 -3
- package/dist/src/components/Status/StatusDisplay.js.map +1 -1
- package/dist/src/components/Table/Table.d.ts.map +1 -1
- package/dist/src/components/Table/Table.js +2 -2
- package/dist/src/components/Table/Table.js.map +1 -1
- package/dist/src/components/Table/TablePagination.d.ts +4 -3
- package/dist/src/components/Table/TablePagination.d.ts.map +1 -1
- package/dist/src/components/Table/TablePagination.js +6 -5
- package/dist/src/components/Table/TablePagination.js.map +1 -1
- package/dist/src/components/common/EditableLabelControl.d.ts.map +1 -1
- package/dist/src/components/common/EditableLabelControl.js +5 -7
- package/dist/src/components/common/EditableLabelControl.js.map +1 -1
- package/dist/src/components/common/TechPreviewBadge.d.ts +4 -0
- package/dist/src/components/common/TechPreviewBadge.d.ts.map +1 -0
- package/dist/src/components/common/TechPreviewBadge.js +23 -0
- package/dist/src/components/common/TechPreviewBadge.js.map +1 -0
- package/dist/src/components/form/LabelsField.d.ts.map +1 -1
- package/dist/src/components/form/LabelsField.js +4 -1
- package/dist/src/components/form/LabelsField.js.map +1 -1
- package/dist/src/components/form/NumberField.d.ts +10 -0
- package/dist/src/components/form/NumberField.d.ts.map +1 -0
- package/dist/src/components/form/NumberField.js +51 -0
- package/dist/src/components/form/NumberField.js.map +1 -0
- package/dist/src/components/form/TextListField.d.ts +12 -0
- package/dist/src/components/form/TextListField.d.ts.map +1 -0
- package/dist/src/components/form/TextListField.js +46 -0
- package/dist/src/components/form/TextListField.js.map +1 -0
- package/dist/src/components/form/validations.d.ts +34 -6
- package/dist/src/components/form/validations.d.ts.map +1 -1
- package/dist/src/components/form/validations.js +78 -4
- package/dist/src/components/form/validations.js.map +1 -1
- package/dist/src/components/modals/DecommissionModal/DecommissionModal.d.ts +9 -0
- package/dist/src/components/modals/DecommissionModal/DecommissionModal.d.ts.map +1 -0
- package/dist/src/components/modals/DecommissionModal/DecommissionModal.js +51 -0
- package/dist/src/components/modals/DecommissionModal/DecommissionModal.js.map +1 -0
- package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.d.ts +4 -2
- package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.d.ts.map +1 -1
- package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.js +11 -4
- package/dist/src/components/modals/EditLabelsModal/EditLabelsForm.js.map +1 -1
- package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.d.ts +10 -0
- package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.d.ts.map +1 -0
- package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.js +67 -0
- package/dist/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.js.map +1 -0
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/hooks/useAppContext.d.ts +1 -1
- package/dist/src/hooks/useAppContext.d.ts.map +1 -1
- package/dist/src/hooks/useFetch.d.ts +1 -1
- package/dist/src/hooks/useFetchPeriodically.js +10 -10
- package/dist/src/hooks/useFetchPeriodically.js.map +1 -1
- package/dist/src/hooks/useTablePagination.d.ts +5 -3
- package/dist/src/hooks/useTablePagination.d.ts.map +1 -1
- package/dist/src/hooks/useTablePagination.js +9 -5
- package/dist/src/hooks/useTablePagination.js.map +1 -1
- package/dist/src/hooks/useWebSocket.d.ts +1 -1
- package/dist/src/hooks/useWebSocket.js +4 -4
- package/dist/src/hooks/useWebSocket.js.map +1 -1
- package/dist/src/links.d.ts +1 -0
- package/dist/src/links.d.ts.map +1 -1
- package/dist/src/links.js +2 -1
- package/dist/src/links.js.map +1 -1
- package/dist/src/types/rbac.d.ts +3 -1
- package/dist/src/types/rbac.d.ts.map +1 -1
- package/dist/src/types/rbac.js +2 -0
- package/dist/src/types/rbac.js.map +1 -1
- package/dist/src/utils/api.d.ts +3 -6
- package/dist/src/utils/api.d.ts.map +1 -1
- package/dist/src/utils/api.js.map +1 -1
- package/dist/src/utils/apiCalls.d.ts +2 -0
- package/dist/src/utils/apiCalls.d.ts.map +1 -0
- package/dist/src/utils/apiCalls.js +23 -0
- package/dist/src/utils/apiCalls.js.map +1 -0
- package/dist/src/utils/devices.d.ts +6 -3
- package/dist/src/utils/devices.d.ts.map +1 -1
- package/dist/src/utils/devices.js +20 -1
- package/dist/src/utils/devices.js.map +1 -1
- package/dist/src/utils/patch.d.ts +4 -1
- package/dist/src/utils/patch.d.ts.map +1 -1
- package/dist/src/utils/patch.js +166 -9
- package/dist/src/utils/patch.js.map +1 -1
- package/dist/src/utils/status/common.js +13 -12
- package/dist/src/utils/status/common.js.map +1 -1
- package/dist/src/utils/status/devices.d.ts +3 -3
- package/dist/src/utils/status/devices.d.ts.map +1 -1
- package/dist/src/utils/status/devices.js +40 -5
- package/dist/src/utils/status/devices.js.map +1 -1
- package/dist/src/utils/status/fleet.d.ts +4 -4
- package/dist/src/utils/status/fleet.d.ts.map +1 -1
- package/dist/src/utils/status/fleet.js +15 -2
- package/dist/src/utils/status/fleet.js.map +1 -1
- package/dist/src/utils/tooltip.d.ts +7 -0
- package/dist/src/utils/tooltip.d.ts.map +1 -0
- package/dist/src/utils/tooltip.js +6 -0
- package/dist/src/utils/tooltip.js.map +1 -0
- package/package.json +1 -1
- package/src/components/DetailsPage/DetailsPageActions.tsx +34 -6
- package/src/components/DetailsPage/Tables/ApplicationsTable.tsx +1 -1
- package/src/components/Device/DeviceDetails/DeviceApplications.tsx +3 -3
- package/src/components/Device/DeviceDetails/DeviceDetailsPage.tsx +53 -34
- package/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx +71 -54
- package/src/components/Device/DeviceDetails/DeviceDetailsTabContent/StatusContent.tsx +75 -0
- package/src/components/Device/DeviceDetails/DeviceDetailsTabContent/SystemResourcesContent.tsx +47 -0
- package/src/components/Device/DeviceDetails/TerminalTab.tsx +1 -4
- package/src/components/Device/DevicesPage/DecommissionedDeviceTableRow.tsx +89 -0
- package/src/components/Device/DevicesPage/DecommissionedDevicesTable.tsx +156 -0
- package/src/components/Device/DevicesPage/DeviceNameOnlyToolbarFilter.tsx +30 -0
- package/src/components/Device/DevicesPage/DevicesEmptyStates.tsx +46 -0
- package/src/components/Device/DevicesPage/DevicesPage.tsx +45 -215
- package/src/components/Device/DevicesPage/{DeviceTableRow.tsx → EnrolledDeviceTableRow.tsx} +16 -20
- package/src/components/Device/DevicesPage/EnrolledDevicesTable.tsx +208 -0
- package/src/components/Device/DevicesPage/useDevices.ts +21 -1
- package/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx +6 -3
- package/src/components/Device/EditDeviceWizard/EditDeviceWizardNav.tsx +1 -1
- package/src/components/Device/EditDeviceWizard/steps/ApplicationTemplates.tsx +2 -0
- package/src/components/Device/EditDeviceWizard/steps/ConfigInlineTemplateForm.tsx +1 -0
- package/src/components/Device/EditDeviceWizard/steps/ConfigurationTemplates.tsx +1 -0
- package/src/components/Device/EditDeviceWizard/steps/ReviewDeviceStep.tsx +27 -19
- package/src/components/Device/EditDeviceWizard/steps/ReviewUpdatePolicy.tsx +55 -0
- package/src/components/Device/EditDeviceWizard/steps/SystemdUnitsForm.tsx +9 -7
- package/src/components/EnrollmentRequest/EnrollmentRequestDetails/EnrollmentRequestDetails.tsx +10 -36
- package/src/components/EnrollmentRequest/EnrollmentRequestList.tsx +2 -2
- package/src/components/EnrollmentRequest/EnrollmentRequestTableRow.tsx +2 -2
- package/src/components/EnrollmentRequest/useEnrollmentRequests.ts +3 -2
- package/src/components/Fleet/CreateFleet/CreateFleetWizard.tsx +46 -5
- package/src/components/Fleet/CreateFleet/CreateFleetWizardFooter.tsx +4 -0
- package/src/components/Fleet/CreateFleet/fleetSpecUtils.ts +62 -0
- package/src/components/Fleet/CreateFleet/steps/ReviewStep.tsx +65 -30
- package/src/components/Fleet/CreateFleet/steps/UpdateConfirmChangesModal.tsx +87 -0
- package/src/components/Fleet/CreateFleet/steps/UpdatePolicyStep.tsx +155 -0
- package/src/components/Fleet/CreateFleet/steps/UpdateStepDisruptionBudget.tsx +91 -0
- package/src/components/Fleet/CreateFleet/steps/UpdateStepRolloutPolicy.tsx +190 -0
- package/src/components/Fleet/CreateFleet/types.ts +25 -0
- package/src/components/Fleet/CreateFleet/utils.ts +20 -1
- package/src/components/Fleet/FleetDetails/FleetDetailsContent.tsx +10 -7
- package/src/components/Fleet/FleetDetails/{FleetDevices.tsx → FleetDevicesCharts.tsx} +4 -4
- package/src/components/Fleet/FleetDetails/FleetDevicesCount.tsx +53 -0
- package/src/components/Fleet/FleetResourceSyncs.tsx +2 -2
- package/src/components/Fleet/FleetRow.tsx +12 -4
- package/src/components/Fleet/FleetsPage.tsx +2 -2
- package/src/components/Fleet/useFleets.ts +7 -7
- package/src/components/ListPage/ListPage.tsx +12 -4
- package/src/components/ListPage/ListPageActions.tsx +50 -16
- package/src/components/ListPage/types.ts +8 -8
- package/src/components/OverviewPage/Cards/Status/DeviceStatusChart.tsx +0 -1
- package/src/components/OverviewPage/OverviewPage.tsx +12 -4
- package/src/components/Repository/RepositoryDetails/RepositoryResourceSyncsCard.tsx +1 -1
- package/src/components/Repository/useRepositories.ts +2 -2
- package/src/components/ResourceSync/RepositoryResourceSyncList.tsx +2 -2
- package/src/components/Status/DeviceLifecycleStatus.tsx +33 -0
- package/src/components/Status/StatusDisplay.tsx +4 -4
- package/src/components/Table/Table.tsx +2 -1
- package/src/components/Table/TablePagination.tsx +9 -7
- package/src/components/common/EditableLabelControl.tsx +7 -6
- package/src/components/common/TechPreviewBadge.tsx +43 -0
- package/src/components/form/LabelsField.tsx +4 -1
- package/src/components/form/NumberField.tsx +78 -0
- package/src/components/form/TextListField.tsx +82 -0
- package/src/components/form/validations.ts +103 -10
- package/src/components/modals/DecommissionModal/DecommissionModal.tsx +95 -0
- package/src/components/modals/EditLabelsModal/EditLabelsForm.tsx +9 -8
- package/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.tsx +130 -0
- package/src/constants.ts +1 -1
- package/src/hooks/useAppContext.tsx +1 -1
- package/src/hooks/useFetchPeriodically.ts +11 -11
- package/src/hooks/{useTablePagination.tsx → useTablePagination.ts} +13 -7
- package/src/hooks/useWebSocket.ts +4 -4
- package/src/links.ts +2 -0
- package/src/types/rbac.ts +2 -0
- package/src/utils/api.ts +13 -6
- package/src/utils/apiCalls.ts +15 -0
- package/src/utils/devices.ts +21 -3
- package/src/utils/patch.ts +182 -8
- package/src/utils/status/common.ts +8 -8
- package/src/utils/status/devices.ts +39 -8
- package/src/utils/status/fleet.ts +21 -6
- package/src/utils/tooltip.ts +2 -0
- package/dist/src/components/DetailsPage/Tables/IntegrityDetails.d.ts +0 -8
- package/dist/src/components/DetailsPage/Tables/IntegrityDetails.d.ts.map +0 -1
- package/dist/src/components/DetailsPage/Tables/IntegrityDetails.js +0 -23
- package/dist/src/components/DetailsPage/Tables/IntegrityDetails.js.map +0 -1
- package/dist/src/components/Device/DevicesPage/DeviceTableRow.d.ts +0 -16
- package/dist/src/components/Device/DevicesPage/DeviceTableRow.d.ts.map +0 -1
- package/dist/src/components/Device/DevicesPage/DeviceTableRow.js.map +0 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDevices.d.ts +0 -9
- package/dist/src/components/Fleet/FleetDetails/FleetDevices.d.ts.map +0 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDevices.js.map +0 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.d.ts +0 -7
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.d.ts.map +0 -1
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.js +0 -13
- package/dist/src/components/Fleet/FleetDetails/FleetDevicesLink.js.map +0 -1
- package/dist/src/components/Status/IntegrityStatus.d.ts +0 -7
- package/dist/src/components/Status/IntegrityStatus.d.ts.map +0 -1
- package/dist/src/components/Status/IntegrityStatus.js +0 -17
- package/dist/src/components/Status/IntegrityStatus.js.map +0 -1
- package/dist/src/utils/status/integrity.d.ts +0 -5
- package/dist/src/utils/status/integrity.d.ts.map +0 -1
- package/dist/src/utils/status/integrity.js +0 -28
- package/dist/src/utils/status/integrity.js.map +0 -1
- package/src/components/DetailsPage/Tables/IntegrityDetails.tsx +0 -44
- package/src/components/Fleet/FleetDetails/FleetDevicesLink.tsx +0 -16
- package/src/components/Status/IntegrityStatus.tsx +0 -19
- package/src/utils/status/integrity.ts +0 -26
|
@@ -31,7 +31,7 @@ const LabelsField: React.FC<LabelsFieldProps> = ({
|
|
|
31
31
|
const errors = await setLabels(newLabels, true);
|
|
32
32
|
const hasErrors = Object.keys(errors || {}).length > 0;
|
|
33
33
|
|
|
34
|
-
onChangeCallback
|
|
34
|
+
onChangeCallback?.(newLabels, hasErrors);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const onDelete = async (_ev: React.MouseEvent<Element, MouseEvent>, index: number) => {
|
|
@@ -44,6 +44,9 @@ const LabelsField: React.FC<LabelsFieldProps> = ({
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
const onAdd = async (text: string) => {
|
|
47
|
+
if (!text) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
47
50
|
const split = text.split('=');
|
|
48
51
|
let newLabel: FlightCtlLabel;
|
|
49
52
|
if (split.length === 2) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useField } from 'formik';
|
|
3
|
+
import { FormGroup, NumberInput, NumberInputProps as PFNumberInputProps } from '@patternfly/react-core';
|
|
4
|
+
import ErrorHelperText, { DefaultHelperText } from './FieldHelperText';
|
|
5
|
+
|
|
6
|
+
export interface NumberFieldProps extends Omit<PFNumberInputProps, 'onChange'> {
|
|
7
|
+
name: string;
|
|
8
|
+
isRequired?: boolean;
|
|
9
|
+
helperText?: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const NumberField = React.forwardRef(
|
|
13
|
+
({ helperText, min = 0, max, isRequired, ...props }: NumberFieldProps, ref: React.Ref<HTMLInputElement>) => {
|
|
14
|
+
const [field, meta, { setValue, setTouched }] = useField<number | ''>({
|
|
15
|
+
name: props.name,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const doChange = (value: number) => {
|
|
19
|
+
let newValue = value < (min || 0) ? min : value;
|
|
20
|
+
newValue = max && newValue > max ? max : newValue;
|
|
21
|
+
if (field.value !== newValue) {
|
|
22
|
+
setValue(newValue);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const onPlus: PFNumberInputProps['onPlus'] = () => {
|
|
27
|
+
doChange(field.value ? field.value + 1 : min);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const onMinus: PFNumberInputProps['onMinus'] = () => {
|
|
31
|
+
doChange(field.value ? field.value - 1 : min);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const handleChange: PFNumberInputProps['onChange'] = (event: React.FormEvent<HTMLInputElement>) => {
|
|
35
|
+
const valStr = (event.target as HTMLInputElement).value;
|
|
36
|
+
// Skip updating the value onBlur. Otherwise, when the field is cleared PF sets a numeric value onBlur.
|
|
37
|
+
if (event.type === 'change') {
|
|
38
|
+
if (!isRequired && valStr === '') {
|
|
39
|
+
setValue('');
|
|
40
|
+
} else {
|
|
41
|
+
const targetValue = valStr as unknown as number;
|
|
42
|
+
doChange(Number.isNaN(targetValue) ? min : Number(targetValue));
|
|
43
|
+
setTouched(true);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const fieldId = `numberfield-${props.name}`;
|
|
49
|
+
const hasError = meta.touched && !!meta.error;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<FormGroup id={`form-control__${fieldId}`} fieldId={fieldId}>
|
|
53
|
+
<NumberInput
|
|
54
|
+
className="fc-number-input"
|
|
55
|
+
{...field}
|
|
56
|
+
{...props}
|
|
57
|
+
// Prevent the NumberInput setting the value to 0 when it's not defined
|
|
58
|
+
value={field.value === undefined && !isRequired ? '' : field.value}
|
|
59
|
+
min={min}
|
|
60
|
+
max={max}
|
|
61
|
+
ref={ref}
|
|
62
|
+
inputName={fieldId}
|
|
63
|
+
onMinus={onMinus}
|
|
64
|
+
onChange={handleChange}
|
|
65
|
+
onPlus={onPlus}
|
|
66
|
+
validated={hasError ? 'error' : 'default'}
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<DefaultHelperText helperText={helperText} />
|
|
70
|
+
<ErrorHelperText meta={meta} />
|
|
71
|
+
</FormGroup>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
NumberField.displayName = 'NumberField';
|
|
77
|
+
|
|
78
|
+
export default NumberField;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useField } from 'formik';
|
|
3
|
+
import { Label, LabelGroup } from '@patternfly/react-core';
|
|
4
|
+
|
|
5
|
+
import EditableLabelControl from '../common/EditableLabelControl';
|
|
6
|
+
import ErrorHelperText, { DefaultHelperText } from './FieldHelperText';
|
|
7
|
+
|
|
8
|
+
type TextListFieldProps = {
|
|
9
|
+
name: string;
|
|
10
|
+
isLoading?: boolean;
|
|
11
|
+
addButtonText?: string;
|
|
12
|
+
helperText?: React.ReactNode;
|
|
13
|
+
onChangeCallback?: (newList: string[], hasErrors: boolean) => void;
|
|
14
|
+
canEdit?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const maxWidth = '16ch';
|
|
18
|
+
|
|
19
|
+
const TextListField = ({ name, onChangeCallback, addButtonText, helperText }: TextListFieldProps) => {
|
|
20
|
+
const [{ value: valueList }, meta, { setValue: setValueList, setTouched }] = useField<string[]>(name);
|
|
21
|
+
const updateValueList = async (newValueList: string[]) => {
|
|
22
|
+
const errors = await setValueList(newValueList, true);
|
|
23
|
+
const hasErrors = Object.keys(errors || {}).length > 0;
|
|
24
|
+
|
|
25
|
+
setTouched(true);
|
|
26
|
+
onChangeCallback?.(newValueList, hasErrors);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const onDelete = async (_ev: React.MouseEvent<Element, MouseEvent>, index: number) => {
|
|
30
|
+
const newValueList = [...valueList];
|
|
31
|
+
newValueList.splice(index, 1);
|
|
32
|
+
await updateValueList(newValueList);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const onAdd = async (text: string) => {
|
|
36
|
+
if (text) {
|
|
37
|
+
await updateValueList([...valueList, text]);
|
|
38
|
+
} else {
|
|
39
|
+
setTouched(true);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const onEdit = async (index: number, newValue: string) => {
|
|
44
|
+
const newLabels = [...valueList];
|
|
45
|
+
newLabels.splice(index, 1, newValue);
|
|
46
|
+
|
|
47
|
+
await updateValueList(newLabels);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
<LabelGroup
|
|
53
|
+
numLabels={5}
|
|
54
|
+
isEditable
|
|
55
|
+
addLabelControl={
|
|
56
|
+
<EditableLabelControl defaultLabel="" addButtonText={addButtonText} onAddLabel={onAdd} isEditable />
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
{valueList.map((text, index) => {
|
|
60
|
+
return (
|
|
61
|
+
<Label
|
|
62
|
+
key={`${text}_${index}`}
|
|
63
|
+
textMaxWidth={maxWidth}
|
|
64
|
+
onClose={(e) => onDelete(e, index)}
|
|
65
|
+
onEditCancel={(_, prevText) => onEdit(index, prevText)}
|
|
66
|
+
onEditComplete={(_, newText) => onEdit(index, newText)}
|
|
67
|
+
/* Add a basic tooltip as the PF tooltip doesn't work for editable labels */
|
|
68
|
+
title={text}
|
|
69
|
+
isEditable
|
|
70
|
+
>
|
|
71
|
+
{text}
|
|
72
|
+
</Label>
|
|
73
|
+
);
|
|
74
|
+
})}
|
|
75
|
+
</LabelGroup>
|
|
76
|
+
<DefaultHelperText helperText={helperText} />
|
|
77
|
+
<ErrorHelperText meta={meta} />
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default TextListField;
|
|
@@ -17,8 +17,7 @@ import {
|
|
|
17
17
|
import { labelToString } from '../../utils/labels';
|
|
18
18
|
import { ApplicationFormSpec } from '../Device/EditDeviceWizard/types';
|
|
19
19
|
import { SystemdUnitFormValue } from '../Device/SystemdUnitsModal/TrackSystemdUnitsForm';
|
|
20
|
-
|
|
21
|
-
type UnvalidatedLabel = Partial<FlightCtlLabel>;
|
|
20
|
+
import { BatchForm, BatchLimitType, DisruptionBudgetForm, RolloutPolicyForm } from '../Fleet/CreateFleet/types';
|
|
22
21
|
|
|
23
22
|
const SYSTEMD_PATTERNS_REGEXP = /^[a-z][a-z0-9-_.]*$/;
|
|
24
23
|
const SYSTEMD_UNITS_MAX_PATTERNS = 256;
|
|
@@ -40,6 +39,8 @@ const BASIC_FLEET_OS_IMAGE_REGEXP = /^[a-zA-Z0-9.\-\/:@_+{}\s]*$/;
|
|
|
40
39
|
const absolutePathRegex = /^\/.*$/;
|
|
41
40
|
export const MAX_TARGET_REVISION_LENGTH = 244;
|
|
42
41
|
|
|
42
|
+
const isInteger = (val: number | undefined) => val === undefined || Number.isInteger(val);
|
|
43
|
+
|
|
43
44
|
export const getLabelValueValidations = (t: TFunction) => [
|
|
44
45
|
{ key: 'labelValueStartAndEnd', message: t('Starts and ends with a letter or a number.') },
|
|
45
46
|
{
|
|
@@ -92,12 +93,12 @@ export const getKubernetesDnsSubdomainErrors = (value: string) => {
|
|
|
92
93
|
return errorKeys;
|
|
93
94
|
};
|
|
94
95
|
|
|
95
|
-
export const hasUniqueLabelKeys = (labels:
|
|
96
|
+
export const hasUniqueLabelKeys = (labels: FlightCtlLabel[]) => {
|
|
96
97
|
const uniqueKeys = new Set(labels.map((label) => label.key));
|
|
97
98
|
return uniqueKeys.size === labels.length;
|
|
98
99
|
};
|
|
99
100
|
|
|
100
|
-
export const getInvalidKubernetesLabels = (labels:
|
|
101
|
+
export const getInvalidKubernetesLabels = (labels: FlightCtlLabel[]) => {
|
|
101
102
|
return labels.filter((unvalidatedLabel) => {
|
|
102
103
|
const key = unvalidatedLabel.key || '';
|
|
103
104
|
const value = unvalidatedLabel.value || '';
|
|
@@ -201,14 +202,13 @@ export const validOsImage = (t: TFunction, { isFleet }: { isFleet: boolean }) =>
|
|
|
201
202
|
export const validLabelsSchema = (t: TFunction) =>
|
|
202
203
|
Yup.array()
|
|
203
204
|
.of(
|
|
204
|
-
Yup.object<
|
|
205
|
-
|
|
206
|
-
key: Yup.string(),
|
|
205
|
+
Yup.object<FlightCtlLabel>().shape({
|
|
206
|
+
key: Yup.string().required(),
|
|
207
207
|
value: Yup.string(),
|
|
208
208
|
}),
|
|
209
209
|
)
|
|
210
210
|
.required()
|
|
211
|
-
.test('missing keys', (labels:
|
|
211
|
+
.test('missing keys', (labels: FlightCtlLabel[], testContext) => {
|
|
212
212
|
const missingKeyLabels = labels.filter((label) => !label.key).map((label) => label.value);
|
|
213
213
|
return missingKeyLabels.length > 0
|
|
214
214
|
? testContext.createError({
|
|
@@ -219,18 +219,32 @@ export const validLabelsSchema = (t: TFunction) =>
|
|
|
219
219
|
: true;
|
|
220
220
|
})
|
|
221
221
|
.test('unique keys', t('Label keys must be unique'), hasUniqueLabelKeys)
|
|
222
|
-
.test('invalid-labels', (labels:
|
|
222
|
+
.test('invalid-labels', (labels: FlightCtlLabel[], testContext) => {
|
|
223
223
|
const invalidLabels = getInvalidKubernetesLabels(labels);
|
|
224
224
|
|
|
225
225
|
return invalidLabels.length > 0
|
|
226
226
|
? testContext.createError({
|
|
227
227
|
message: t('The following labels are not valid Kubernetes labels: {{invalidLabels}}', {
|
|
228
|
-
invalidLabels: `${invalidLabels.map(
|
|
228
|
+
invalidLabels: `${invalidLabels.map(labelToString).join(', ')}`,
|
|
229
229
|
}),
|
|
230
230
|
})
|
|
231
231
|
: true;
|
|
232
232
|
});
|
|
233
233
|
|
|
234
|
+
export const validGroupLabelKeysSchema = (t: TFunction) =>
|
|
235
|
+
Yup.array()
|
|
236
|
+
.of(
|
|
237
|
+
Yup.string()
|
|
238
|
+
.required()
|
|
239
|
+
.test('only-label-keys', t("Full labels are not allowed, use only the 'key' part."), (value?: string) => {
|
|
240
|
+
return !value?.includes('=');
|
|
241
|
+
}),
|
|
242
|
+
)
|
|
243
|
+
.test('unique keys', t('Label keys must be unique'), (labelKeys) => {
|
|
244
|
+
const uniqueKeys = new Set(labelKeys);
|
|
245
|
+
return uniqueKeys.size === labelKeys?.length;
|
|
246
|
+
});
|
|
247
|
+
|
|
234
248
|
export const validApplicationsSchema = (t: TFunction) => {
|
|
235
249
|
return Yup.array()
|
|
236
250
|
.of(
|
|
@@ -287,6 +301,85 @@ export const validApplicationsSchema = (t: TFunction) => {
|
|
|
287
301
|
});
|
|
288
302
|
};
|
|
289
303
|
|
|
304
|
+
export const validFleetRolloutPolicySchema = (t: TFunction) => {
|
|
305
|
+
return Yup.object()
|
|
306
|
+
.shape({
|
|
307
|
+
isAdvanced: Yup.boolean().required(),
|
|
308
|
+
updateTimeout: Yup.number()
|
|
309
|
+
.required('Update timeout is required')
|
|
310
|
+
.test('not-decimal', t('Cannot be decimal'), isInteger),
|
|
311
|
+
batches: Yup.array()
|
|
312
|
+
.of(
|
|
313
|
+
Yup.lazy((values: BatchForm) =>
|
|
314
|
+
Yup.object<BatchForm>().shape({
|
|
315
|
+
selector: validLabelsSchema(t),
|
|
316
|
+
limitType: Yup.string()
|
|
317
|
+
.oneOf([BatchLimitType.BatchLimitAbsoluteNumber, BatchLimitType.BatchLimitPercent])
|
|
318
|
+
.required(),
|
|
319
|
+
limit: Yup.number()
|
|
320
|
+
.test('correct-percentage', t('Percentage must be between 1 and 100.'), (num) => {
|
|
321
|
+
if (num === undefined) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
if (values.limitType === BatchLimitType.BatchLimitPercent && num > 100) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
return true;
|
|
328
|
+
})
|
|
329
|
+
.test('not-decimal', t('Cannot be decimal'), isInteger)
|
|
330
|
+
// When an absolute number, we can only restrict the minimum value
|
|
331
|
+
.min(1, t('Value must be greater or equal than 1')),
|
|
332
|
+
successThreshold: Yup.number()
|
|
333
|
+
.required('Success threshold is required')
|
|
334
|
+
.min(1, t('Success threshold must be between 1 and 100'))
|
|
335
|
+
.max(100, t('Success threshold must be between 1 and 100'))
|
|
336
|
+
.test('not-decimal', t('Cannot be decimal'), isInteger),
|
|
337
|
+
}),
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
.required(),
|
|
341
|
+
})
|
|
342
|
+
.test('valid-rollout', (rolloutPolicy: RolloutPolicyForm | undefined, testContext) => {
|
|
343
|
+
if (!rolloutPolicy || rolloutPolicy.batches.length === 0) {
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const errors = rolloutPolicy.batches.reduce((errors, batch, batchIndex) => {
|
|
348
|
+
const hasError = batch.limit === undefined && Object.keys(batch.selector || {}).length === 0;
|
|
349
|
+
if (hasError) {
|
|
350
|
+
errors.push(
|
|
351
|
+
new Yup.ValidationError(
|
|
352
|
+
t('At least one of the label selector or numeric selector must be specified.'),
|
|
353
|
+
'',
|
|
354
|
+
`rolloutPolicy.batches[${batchIndex}]`,
|
|
355
|
+
),
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return errors;
|
|
359
|
+
}, [] as Yup.ValidationError[]);
|
|
360
|
+
|
|
361
|
+
return testContext.createError({
|
|
362
|
+
message: () => errors,
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
export const validFleetDisruptionBudgetSchema = (t: TFunction) => {
|
|
368
|
+
return Yup.object()
|
|
369
|
+
.shape({
|
|
370
|
+
isAdvanced: Yup.boolean().required(),
|
|
371
|
+
minAvailable: Yup.number().test('not-decimal', t('Number of devices cannot be decimal'), isInteger),
|
|
372
|
+
maxUnavailable: Yup.number().test('not-decimal', t('Number of devices cannot be decimal'), isInteger),
|
|
373
|
+
groupBy: validGroupLabelKeysSchema(t),
|
|
374
|
+
})
|
|
375
|
+
.test(
|
|
376
|
+
'has-min-or-max',
|
|
377
|
+
t('At least one of minimum available or maximum unavailable devices is required.'),
|
|
378
|
+
(value: DisruptionBudgetForm) =>
|
|
379
|
+
!(value.isAdvanced && value.minAvailable === undefined && value.maxUnavailable === undefined),
|
|
380
|
+
);
|
|
381
|
+
};
|
|
382
|
+
|
|
290
383
|
export const validConfigTemplatesSchema = (t: TFunction) =>
|
|
291
384
|
Yup.array()
|
|
292
385
|
.test('unique-names', t('Source names must be unique'), (templates: SpecConfigTemplate[] | undefined) => {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Formik } from 'formik';
|
|
3
|
+
import { Alert, Button, Modal, Stack, StackItem } from '@patternfly/react-core';
|
|
4
|
+
|
|
5
|
+
import { DeviceDecommissionTargetType } from '@flightctl/types';
|
|
6
|
+
|
|
7
|
+
import { useTranslation } from '../../../hooks/useTranslation';
|
|
8
|
+
import { getErrorMessage } from '../../../utils/error';
|
|
9
|
+
|
|
10
|
+
type DecommissionModalProps = {
|
|
11
|
+
onDecommission: (target: DeviceDecommissionTargetType) => Promise<unknown>;
|
|
12
|
+
onClose: VoidFunction;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type DecommissionFormValues = {
|
|
16
|
+
// Currently not implemented - no checkbox to select this option is visible in the UI
|
|
17
|
+
doFactoryReset: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const DecommissionModal = ({ onDecommission, onClose }: DecommissionModalProps) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const [isDecommissioning, setIsDecommissioning] = React.useState(false);
|
|
23
|
+
const [error, setError] = React.useState<string>();
|
|
24
|
+
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
// Clean-up after the modal closes for any reason
|
|
27
|
+
return () => {
|
|
28
|
+
setIsDecommissioning(false);
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Modal title={t('Decommission device?')} isOpen onClose={onClose} variant="small" titleIconVariant="warning">
|
|
34
|
+
<Formik<DecommissionFormValues>
|
|
35
|
+
initialValues={{
|
|
36
|
+
doFactoryReset: false,
|
|
37
|
+
}}
|
|
38
|
+
onSubmit={({ doFactoryReset }) => {
|
|
39
|
+
const doSubmit = async () => {
|
|
40
|
+
setError(undefined);
|
|
41
|
+
try {
|
|
42
|
+
setIsDecommissioning(true);
|
|
43
|
+
await onDecommission(
|
|
44
|
+
doFactoryReset
|
|
45
|
+
? DeviceDecommissionTargetType.DeviceDecommissionTargetTypeFactoryReset
|
|
46
|
+
: DeviceDecommissionTargetType.DeviceDecommissionTargetTypeUnenroll,
|
|
47
|
+
);
|
|
48
|
+
onClose();
|
|
49
|
+
} catch (err) {
|
|
50
|
+
setError(getErrorMessage(err));
|
|
51
|
+
setIsDecommissioning(false);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
void doSubmit();
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{({ submitForm }) => {
|
|
58
|
+
return (
|
|
59
|
+
<Stack hasGutter>
|
|
60
|
+
<StackItem>{t('Are you sure you want to proceed with decommissioning this device?')}</StackItem>
|
|
61
|
+
<StackItem>
|
|
62
|
+
{t(
|
|
63
|
+
'Decommissioned devices will not be able to communicate with the edge management system anymore, and they will be removed from any fleet they were associated to. Once decommissioned, the device cannot be managed further.',
|
|
64
|
+
)}
|
|
65
|
+
</StackItem>
|
|
66
|
+
{error && (
|
|
67
|
+
<StackItem>
|
|
68
|
+
<Alert isInline variant="danger" title={t('An error occurred')}>
|
|
69
|
+
{error}
|
|
70
|
+
</Alert>
|
|
71
|
+
</StackItem>
|
|
72
|
+
)}
|
|
73
|
+
<StackItem>
|
|
74
|
+
<Button
|
|
75
|
+
key="confirm"
|
|
76
|
+
variant="danger"
|
|
77
|
+
isDisabled={isDecommissioning}
|
|
78
|
+
isLoading={isDecommissioning}
|
|
79
|
+
onClick={submitForm}
|
|
80
|
+
>
|
|
81
|
+
{t('Decommission device')}
|
|
82
|
+
</Button>
|
|
83
|
+
<Button key="cancel" variant="link" onClick={onClose} isDisabled={isDecommissioning}>
|
|
84
|
+
{t('Cancel')}
|
|
85
|
+
</Button>
|
|
86
|
+
</StackItem>
|
|
87
|
+
</Stack>
|
|
88
|
+
);
|
|
89
|
+
}}
|
|
90
|
+
</Formik>
|
|
91
|
+
</Modal>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default DecommissionModal;
|
|
@@ -15,6 +15,7 @@ import { fromAPILabel } from '../../../utils/labels';
|
|
|
15
15
|
import { validLabelsSchema } from '../../form/validations';
|
|
16
16
|
import { getErrorMessage } from '../../../utils/error';
|
|
17
17
|
import { getLabelPatches } from '../../../utils/patch';
|
|
18
|
+
import LabelsView from '../../common/LabelsView';
|
|
18
19
|
|
|
19
20
|
type EditLabelsFormValues = {
|
|
20
21
|
labels: FlightCtlLabel[];
|
|
@@ -23,7 +24,6 @@ type EditLabelsFormValues = {
|
|
|
23
24
|
type EditLabelsFormContentProps = {
|
|
24
25
|
isSubmitting: FormikProps<EditLabelsFormValues>['isSubmitting'];
|
|
25
26
|
submitForm: (values: EditLabelsFormValues) => Promise<string>;
|
|
26
|
-
canEdit: boolean;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const getValidationSchema = (t: TFunction) => {
|
|
@@ -34,7 +34,7 @@ const getValidationSchema = (t: TFunction) => {
|
|
|
34
34
|
|
|
35
35
|
const delayResponse = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
36
36
|
|
|
37
|
-
const EditLabelsFormContent = ({ isSubmitting, submitForm
|
|
37
|
+
const EditLabelsFormContent = ({ isSubmitting, submitForm }: EditLabelsFormContentProps) => {
|
|
38
38
|
const { t } = useTranslation();
|
|
39
39
|
const [submitError, setSubmitError] = React.useState<string>();
|
|
40
40
|
|
|
@@ -56,7 +56,6 @@ const EditLabelsFormContent = ({ isSubmitting, submitForm, canEdit }: EditLabels
|
|
|
56
56
|
addButtonText={isSubmitting ? t('Saving...') : undefined}
|
|
57
57
|
isLoading={isSubmitting}
|
|
58
58
|
onChangeCallback={debouncedSubmit}
|
|
59
|
-
canEdit={canEdit}
|
|
60
59
|
/>
|
|
61
60
|
{submitError && <Alert isInline title={submitError} variant="danger" />}
|
|
62
61
|
</FlightCtlForm>
|
|
@@ -66,10 +65,14 @@ const EditLabelsFormContent = ({ isSubmitting, submitForm, canEdit }: EditLabels
|
|
|
66
65
|
type EditLabelsFormProps = {
|
|
67
66
|
device: Device;
|
|
68
67
|
onDeviceUpdate: () => void;
|
|
69
|
-
canEdit: boolean;
|
|
70
68
|
};
|
|
71
69
|
|
|
72
|
-
const
|
|
70
|
+
export const ViewLabels = ({ device }: { device: Device }) => {
|
|
71
|
+
const currentLabels = device.metadata.labels || {};
|
|
72
|
+
return <LabelsView prefix="read-only-labels" labels={currentLabels} />;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const EditLabelsForm = ({ device, onDeviceUpdate }: EditLabelsFormProps) => {
|
|
73
76
|
const { t } = useTranslation();
|
|
74
77
|
const { patch } = useFetch();
|
|
75
78
|
|
|
@@ -96,9 +99,7 @@ const EditLabelsForm = ({ device, onDeviceUpdate, canEdit }: EditLabelsFormProps
|
|
|
96
99
|
}}
|
|
97
100
|
validationSchema={getValidationSchema(t)}
|
|
98
101
|
>
|
|
99
|
-
{({ isSubmitting, submitForm }) =>
|
|
100
|
-
<EditLabelsFormContent canEdit={canEdit} isSubmitting={isSubmitting} submitForm={submitForm} />
|
|
101
|
-
)}
|
|
102
|
+
{({ isSubmitting, submitForm }) => <EditLabelsFormContent isSubmitting={isSubmitting} submitForm={submitForm} />}
|
|
102
103
|
</Formik>
|
|
103
104
|
);
|
|
104
105
|
};
|
package/src/components/modals/massModals/MassDecommissionDeviceModal/MassDecommissionDeviceModal.tsx
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Alert, Button, Modal, Progress, ProgressMeasureLocation, Stack, StackItem } from '@patternfly/react-core';
|
|
3
|
+
import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
|
|
4
|
+
|
|
5
|
+
import { Device, DeviceDecommission, DeviceDecommissionTargetType } from '@flightctl/types';
|
|
6
|
+
|
|
7
|
+
import { getErrorMessage } from '../../../../utils/error';
|
|
8
|
+
import { useFetch } from '../../../../hooks/useFetch';
|
|
9
|
+
import { useTranslation } from '../../../../hooks/useTranslation';
|
|
10
|
+
import { isPromiseRejected } from '../../../../types/typeUtils';
|
|
11
|
+
import ResourceLink from '../../../common/ResourceLink';
|
|
12
|
+
|
|
13
|
+
type MassDecommissionDeviceModalProps = {
|
|
14
|
+
devices: Array<Device>;
|
|
15
|
+
onClose: VoidFunction;
|
|
16
|
+
onSuccess: VoidFunction;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const MassDecommissionDeviceModal = ({ onClose, devices, onSuccess }: MassDecommissionDeviceModalProps) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
const [progress, setProgress] = React.useState(0);
|
|
22
|
+
const [totalProgress, setTotalProgress] = React.useState(0);
|
|
23
|
+
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
24
|
+
const [errors, setErrors] = React.useState<string[]>();
|
|
25
|
+
const { put } = useFetch();
|
|
26
|
+
|
|
27
|
+
const decommissionDevices = async () => {
|
|
28
|
+
setProgress(0);
|
|
29
|
+
setIsSubmitting(true);
|
|
30
|
+
const promises = devices.map(async (dev) => {
|
|
31
|
+
await put<DeviceDecommission>(`devices/${dev.metadata.name}/decommission`, {
|
|
32
|
+
target: DeviceDecommissionTargetType.DeviceDecommissionTargetTypeUnenroll,
|
|
33
|
+
});
|
|
34
|
+
setProgress((p) => p + 1);
|
|
35
|
+
});
|
|
36
|
+
setTotalProgress(promises.length);
|
|
37
|
+
const results = await Promise.allSettled(promises);
|
|
38
|
+
setIsSubmitting(false);
|
|
39
|
+
|
|
40
|
+
const rejectedResults = results.filter(isPromiseRejected);
|
|
41
|
+
|
|
42
|
+
if (rejectedResults.length) {
|
|
43
|
+
setErrors(rejectedResults.map((r) => getErrorMessage(r.reason)));
|
|
44
|
+
} else {
|
|
45
|
+
onSuccess();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Modal
|
|
51
|
+
title={t('Decommission devices ?')}
|
|
52
|
+
isOpen
|
|
53
|
+
onClose={onClose}
|
|
54
|
+
showClose={!isSubmitting}
|
|
55
|
+
titleIconVariant="warning"
|
|
56
|
+
variant="medium"
|
|
57
|
+
actions={[
|
|
58
|
+
<Button
|
|
59
|
+
key="decommission"
|
|
60
|
+
variant="danger"
|
|
61
|
+
onClick={decommissionDevices}
|
|
62
|
+
isLoading={isSubmitting}
|
|
63
|
+
isDisabled={isSubmitting}
|
|
64
|
+
>
|
|
65
|
+
{t('Decommission')}
|
|
66
|
+
</Button>,
|
|
67
|
+
<Button key="cancel" variant="link" onClick={onClose} isDisabled={isSubmitting}>
|
|
68
|
+
{t('Cancel')}
|
|
69
|
+
</Button>,
|
|
70
|
+
]}
|
|
71
|
+
>
|
|
72
|
+
<Stack hasGutter>
|
|
73
|
+
<StackItem>{t('Are you sure you want to proceed with decommissioning these devices ?')}</StackItem>
|
|
74
|
+
<StackItem>
|
|
75
|
+
{t(
|
|
76
|
+
'Decommissioned devices will not be able to communicate with the edge management system anymore, and they will be removed from any fleet they were associated to. Once decommissioned, the devices cannot be managed further.',
|
|
77
|
+
)}
|
|
78
|
+
</StackItem>
|
|
79
|
+
<StackItem>
|
|
80
|
+
<Table>
|
|
81
|
+
<Thead>
|
|
82
|
+
<Tr>
|
|
83
|
+
<Th>{t('Name')}</Th>
|
|
84
|
+
<Th>{t('Alias')}</Th>
|
|
85
|
+
</Tr>
|
|
86
|
+
</Thead>
|
|
87
|
+
<Tbody>
|
|
88
|
+
{devices.map((device) => {
|
|
89
|
+
return (
|
|
90
|
+
<Tr key={device.metadata.name}>
|
|
91
|
+
<Td dataLabel={t('Name')}>
|
|
92
|
+
<ResourceLink id={device.metadata.name as string} />
|
|
93
|
+
</Td>
|
|
94
|
+
<Td dataLabel={t('Alias')}>{device.metadata.labels?.alias || '-'}</Td>
|
|
95
|
+
</Tr>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
98
|
+
</Tbody>
|
|
99
|
+
</Table>
|
|
100
|
+
</StackItem>
|
|
101
|
+
{isSubmitting && (
|
|
102
|
+
<StackItem>
|
|
103
|
+
<Progress
|
|
104
|
+
value={progress}
|
|
105
|
+
min={0}
|
|
106
|
+
max={totalProgress}
|
|
107
|
+
title={t('Decommissioning...')}
|
|
108
|
+
measureLocation={ProgressMeasureLocation.top}
|
|
109
|
+
label={t('{{progress}} of {{totalProgress}}', { progress, totalProgress })}
|
|
110
|
+
valueText={t('{{progress}} of {{totalProgress}}', { progress, totalProgress })}
|
|
111
|
+
/>
|
|
112
|
+
</StackItem>
|
|
113
|
+
)}
|
|
114
|
+
{errors?.length && (
|
|
115
|
+
<StackItem>
|
|
116
|
+
<Alert isInline variant="danger" title={t('An error occurred')}>
|
|
117
|
+
<Stack hasGutter>
|
|
118
|
+
{errors.map((e, index) => (
|
|
119
|
+
<StackItem key={index}>{e}</StackItem>
|
|
120
|
+
))}
|
|
121
|
+
</Stack>
|
|
122
|
+
</Alert>
|
|
123
|
+
</StackItem>
|
|
124
|
+
)}
|
|
125
|
+
</Stack>
|
|
126
|
+
</Modal>
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export default MassDecommissionDeviceModal;
|
package/src/constants.ts
CHANGED
|
@@ -59,7 +59,7 @@ export type AppContextProps = {
|
|
|
59
59
|
Prompt?: PromptFC;
|
|
60
60
|
};
|
|
61
61
|
fetch: {
|
|
62
|
-
getWsEndpoint: () => { wsEndpoint: string; protocols: string[] };
|
|
62
|
+
getWsEndpoint: (deviceId: string) => { wsEndpoint: string; protocols: string[] };
|
|
63
63
|
get: <R>(kind: string, abortSignal?: AbortSignal) => Promise<R>;
|
|
64
64
|
post: <R>(kind: string, data: R, abortSignal?: AbortSignal) => Promise<R>;
|
|
65
65
|
put: <R>(kind: string, data: R, abortSignal?: AbortSignal) => Promise<R>;
|