From 6de2b1a607449fa12d6d3a1058866561598d463e Mon Sep 17 00:00:00 2001 From: Celia Amador Date: Thu, 13 Nov 2025 12:23:12 +0100 Subject: [PATCH 1/2] EDM-2422: Split applications and systemd units statuses --- libs/i18n/locales/en/translation.json | 17 +- .../DetailsPage/Tables/ApplicationsTable.css | 7 - .../DetailsPage/Tables/ApplicationsTable.tsx | 152 ++---------------- .../DetailsPage/Tables/SystemdUnitsTable.tsx | 93 +++++++++++ .../DeviceDetails/DeviceApplications.tsx | 76 +-------- .../Device/DeviceDetails/DeviceDetailsTab.tsx | 8 +- .../DeviceDetails/DeviceSystemdUnits.tsx | 30 ++++ .../EditDeviceWizard/EditDeviceWizard.tsx | 9 +- .../EditDeviceWizard/deviceSpecUtils.ts | 10 ++ .../steps/DeviceTemplateStep.tsx | 2 +- .../Device/EditDeviceWizard/utils.ts | 16 +- .../src/components/Fleet/CreateFleet/utils.ts | 6 +- 12 files changed, 194 insertions(+), 232 deletions(-) delete mode 100644 libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.css create mode 100644 libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx create mode 100644 libs/ui-components/src/components/Device/DeviceDetails/DeviceSystemdUnits.tsx diff --git a/libs/i18n/locales/en/translation.json b/libs/i18n/locales/en/translation.json index 70f6ff3e1..11475bb76 100644 --- a/libs/i18n/locales/en/translation.json +++ b/libs/i18n/locales/en/translation.json @@ -120,16 +120,18 @@ "Status": "Status", "Ready": "Ready", "Restarts": "Restarts", - "Type": "Type", - "Delete system service": "Delete system service", - "Waiting for service to be reported...": "Waiting for service to be reported...", - "App": "App", - "Systemd": "Systemd", - "{{ appName }} is being removed, this may take some time.": "{{ appName }} is being removed, this may take some time.", "No applications found": "No applications found", + "Type": "Type", "Reason": "Reason", "Message": "Message", "No conditions found": "No conditions found", + "Enable state": "Enable state", + "Load state": "Load state", + "Active state": "Active state", + "Sub state": "Sub state", + "System services table": "System services table", + "No system services found": "No system services found", + "System services can be configured via the device specification": "System services can be configured via the device specification", "Add devices": "Add devices", "You can add devices following these steps:": "You can add devices following these steps:", "Request an enrollment certificate for your device": "Request an enrollment certificate for your device", @@ -143,7 +145,6 @@ "Edit alias": "Edit alias", "Device alias could not be updated": "Device alias could not be updated", "Applications": "Applications", - "Track systemd services": "Track systemd services", "Delete forever": "Delete forever", "You are about to resume <1>{deviceNameOrAlias}": "You are about to resume <1>{deviceNameOrAlias}", "Details": "Details", @@ -179,6 +180,7 @@ "Device is owned by more than one fleet:": "Device is owned by more than one fleet:", "System image mismatch": "System image mismatch", "Desired system image: {{ desiredOsImage }}": "Desired system image: {{ desiredOsImage }}", + "System services": "System services", "Connection was closed": "Connection was closed", "Reconnect": "Reconnect", "Show decommissioned devices": "Show decommissioned devices", @@ -319,6 +321,7 @@ "Maximum unavailable devices: {{ maxUnavailable }}": "Maximum unavailable devices: {{ maxUnavailable }}", "Add service": "Add service", "Tracked systemd services": "Tracked systemd services", + "Track systemd services": "Track systemd services", "Systemd service name": "Systemd service name", "Track services": "Track services", "Approve": "Approve", diff --git a/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.css b/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.css deleted file mode 100644 index 340cc1c2f..000000000 --- a/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.css +++ /dev/null @@ -1,7 +0,0 @@ -.fctl-applications-table__row .pf-v5-c-button { - visibility: hidden; -} - -.fctl-applications-table__row:hover .pf-v5-c-button { - visibility: visible; -} diff --git a/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.tsx b/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.tsx index cf08ff023..7332106b6 100644 --- a/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.tsx +++ b/libs/ui-components/src/components/DetailsPage/Tables/ApplicationsTable.tsx @@ -1,74 +1,33 @@ import * as React from 'react'; -import { Bullseye, Button, Spinner } from '@patternfly/react-core'; +import { Bullseye } from '@patternfly/react-core'; import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; -import MinusCircleIcon from '@patternfly/react-icons/dist/js/icons/minus-circle-icon'; import { DeviceApplicationStatus } from '@flightctl/types'; import { useTranslation } from '../../../hooks/useTranslation'; import ApplicationStatus from '../../Status/ApplicationStatus'; -import WithTooltip from '../../common/WithTooltip'; - -import './ApplicationsTable.css'; type ApplicationsTableProps = { - // Contains the statuses of all detected applications and systemdUnits + // Contains the statuses of all detected applications appsStatus: DeviceApplicationStatus[]; // List of apps as defined the device / fleet spec specApps: string[]; - // List of systemd units as defined in the device / fleet spec - specSystemdUnits: string[]; - // Map: (systemdUnitName, timeItWasAdded) - addedSystemdUnitDates: Record; - onSystemdDelete?: (deletedUnit: string) => void; - isUpdating: boolean; - canEdit: boolean; }; -const DELETE_SYSTED_TIMEOUT = 30000; // 30 seconds - -const ApplicationsTable = ({ - appsStatus, - specApps, - specSystemdUnits, - addedSystemdUnitDates, - onSystemdDelete, - isUpdating, - canEdit, -}: ApplicationsTableProps) => { +const ApplicationsTable = ({ appsStatus, specApps }: ApplicationsTableProps) => { const { t } = useTranslation(); - // Required to be able to detect removed systemd units for their correct type. - // It takes a bit for them to be removed from the applications list. - const [deletedSystemdUnits, setDeletedSystemdUnits] = React.useState([]); - - React.useEffect(() => { - // Remove a service from the deleted list if it was added back later - const filtered = deletedSystemdUnits.filter((deletedUnit) => { - if (addedSystemdUnitDates[deletedUnit]) { - return false; - } - return true; - }); - if (filtered.length < deletedSystemdUnits.length) { - setDeletedSystemdUnits(filtered); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [addedSystemdUnitDates]); - - const appsAndSystemdUnits: string[] = []; + // Includes applications already reported in status as well as those that are only in the spec yet + const allAppNames: string[] = []; specApps.forEach((app) => { - appsAndSystemdUnits.push(app); - }); - specSystemdUnits.forEach((systemdUnit) => { - appsAndSystemdUnits.push(systemdUnit); + allAppNames.push(app); }); appsStatus.forEach((appStatus) => { - if (!appsAndSystemdUnits.includes(appStatus.name)) { - appsAndSystemdUnits.push(appStatus.name); + if (!allAppNames.includes(appStatus.name)) { + allAppNames.push(appStatus.name); } }); - return appsAndSystemdUnits.length ? ( + return allAppNames.length ? ( @@ -76,101 +35,24 @@ const ApplicationsTable = ({ - - {appsAndSystemdUnits.map((appName) => { - const appDetails = appsStatus.find((app) => app.name === appName); - const isDeletedSystemdUnit = deletedSystemdUnits.includes(appName); - const isAddedSystemdUnit = !!addedSystemdUnitDates[appName]; - const isApp = - specApps.includes(appName) || - !(specSystemdUnits.includes(appName) || isDeletedSystemdUnit || isAddedSystemdUnit); - - const deleteSystemdUnit = canEdit && !isDeletedSystemdUnit && onSystemdDelete && ( - - - - - {!showSpinner && } - {!showSpinner && } - - - ); - } - - let typeColumnContent: React.ReactNode; - - if (isApp) { - typeColumnContent = t('App'); - } else if (onSystemdDelete) { - let extraContent: React.ReactNode; - if (isDeletedSystemdUnit) { - extraContent = ( - - - - ); - } else { - extraContent = deleteSystemdUnit; - } - - typeColumnContent = ( - <> - {t('Systemd')} {extraContent} - - ); - } else { - typeColumnContent = t('Systemd'); - } + {allAppNames.map((appName) => { + const appDetails = appsStatus.find((app) => app.name === appName) || { + status: null, + ready: '-', + restarts: '-', + }; return ( - + - ); })} diff --git a/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx b/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx new file mode 100644 index 000000000..876e0141d --- /dev/null +++ b/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx @@ -0,0 +1,93 @@ +import * as React from 'react'; +import { Bullseye, EmptyState, EmptyStateBody, EmptyStateVariant, Label } from '@patternfly/react-core'; +import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; +import { CogIcon } from '@patternfly/react-icons/dist/js/icons/cog-icon'; +import { ClockIcon } from '@patternfly/react-icons/dist/js/icons/clock-icon'; + +import { SystemdUnitStatus } from '@flightctl/types'; +import { useTranslation } from '../../../hooks/useTranslation'; + +const serviceRegex = /\.service$/; +const timerRegex = /\.timer$/; + +const SystemdUnitStatusIcon = ({ unitName }: { unitName: string }) => { + if (serviceRegex.test(unitName)) { + return ; + } + if (timerRegex.test(unitName)) { + return ; + } + return null; +}; + +type SystemdUnitsTableProps = { + systemdUnitsStatus: SystemdUnitStatus[]; +}; + +const SystemdUnitRow = ({ unitStatus }: { unitStatus: SystemdUnitStatus }) => { + const { t } = useTranslation(); + + return ( + + + + + + + + ); +}; + +// Contrary to applications, we don't show the matchPatterns that were defined in the device spec. +// Since these may contain glob patterns, etc, we can't reliably translate the patterns to a list of units. +const SystemdUnitsTable = ({ systemdUnitsStatus }: SystemdUnitsTableProps) => { + const { t } = useTranslation(); + + return systemdUnitsStatus.length ? ( +
{t('Status')} {t('Ready')} {t('Restarts')}{t('Type')}
{appName} - {showSpinner ? ( - <> - {t('Waiting for service to be reported...')} - - ) : ( - '-' - )} - -- - {isApp ? ( - <>{t('App')} - ) : ( - <> - {t('Systemd')} {deleteSystemdUnit} - - )} -
{appName} - + {appDetails.status ? : '-'} {appDetails.ready} {appDetails.restarts}{typeColumnContent}
+ {unitStatus.unit} + + + + + + + + +
+ + + + + + + + + + + {systemdUnitsStatus.map((unitStatus) => { + return ; + })} + +
{t('Name')}{t('Enable state')}{t('Load state')}{t('Active state')}{t('Sub state')}
+ ) : ( + + + +

{t('No system services found')}

+

{t('System services can be configured via the device specification')}

+
+
+
+ ); +}; + +export default SystemdUnitsTable; diff --git a/libs/ui-components/src/components/Device/DeviceDetails/DeviceApplications.tsx b/libs/ui-components/src/components/Device/DeviceDetails/DeviceApplications.tsx index 684359ca9..e54c4220b 100644 --- a/libs/ui-components/src/components/Device/DeviceDetails/DeviceApplications.tsx +++ b/libs/ui-components/src/components/Device/DeviceDetails/DeviceApplications.tsx @@ -1,46 +1,19 @@ import * as React from 'react'; -import { Button, CardTitle, Flex, FlexItem } from '@patternfly/react-core'; +import { CardTitle, Flex, FlexItem } from '@patternfly/react-core'; import { Device } from '@flightctl/types'; import { useTranslation } from '../../../hooks/useTranslation'; -import { useFetch } from '../../../hooks/useFetch'; -import { getStringListPatches } from '../../../utils/patch'; -import { getDeviceFleet } from '../../../utils/devices'; -import SystemdUnitsModal from '../SystemdUnitsModal/SystemdUnitsModal'; import ApplicationsTable from '../../DetailsPage/Tables/ApplicationsTable'; import DetailsPageCard, { DetailsPageCardBody } from '../../DetailsPage/DetailsPageCard'; import { isImageAppProvider } from '../../../types/deviceSpec'; type DeviceDetailsTabProps = { device: Required; - canEdit: boolean; - refetch?: VoidFunction; }; -const DeviceApplications = ({ device, refetch, canEdit }: React.PropsWithChildren) => { +const DeviceApplications = ({ device }: DeviceDetailsTabProps) => { const { t } = useTranslation(); - const { patch } = useFetch(); - const [showSystemdModal, setShowSystemdModal] = React.useState(false); - const [isUpdating, setIsUpdating] = React.useState(false); - const [addedSystemdDates, setAddedSystemdDates] = React.useState>({}); - const onClose = (hasChanges?: boolean, addedUnits?: string[]) => { - if (hasChanges) { - refetch?.(); - } - if (addedUnits?.length) { - const allAddedUnitDates = { ...addedSystemdDates }; - const addedDate = Date.now(); - addedUnits.forEach((newUnit) => { - allAddedUnitDates[newUnit] = addedDate; - }); - setAddedSystemdDates(allAddedUnitDates); - } - setShowSystemdModal(false); - }; - - const isManagedDevice = !!getDeviceFleet(device.metadata); - const trackedSystemdUnits = device.spec?.systemd?.matchPatterns || []; const specApps = device.spec?.applications?.map((app) => { if (isImageAppProvider(app)) { @@ -48,59 +21,16 @@ const DeviceApplications = ({ device, refetch, canEdit }: React.PropsWithChildre } return app.name as string; }) || []; - const apps = device.status.applications; // includes available systemdUnits - - const deleteSystemdUnit = isManagedDevice - ? undefined - : (removedUnit: string) => { - const updateDeviceSpec = async () => { - const patches = getStringListPatches( - '/spec/systemd', - trackedSystemdUnits, - trackedSystemdUnits.filter((unit) => unit !== removedUnit), - (units: string[]) => ({ matchPatterns: units }), - ); - if (patches.length > 0) { - setIsUpdating(true); - await patch(`devices/${device.metadata.name}`, patches); - refetch?.(); - setIsUpdating(false); - } - }; - void updateDeviceSpec(); - }; return ( {t('Applications')} - {!isManagedDevice && canEdit && ( - - - - )} - - {showSystemdModal && } + ); diff --git a/libs/ui-components/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx b/libs/ui-components/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx index 6ca33e102..e45aae43d 100644 --- a/libs/ui-components/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx +++ b/libs/ui-components/src/components/Device/DeviceDetails/DeviceDetailsTab.tsx @@ -26,6 +26,7 @@ import DeviceLifecycleStatus from '../../Status/DeviceLifecycleStatus'; import DeviceFleet from './DeviceFleet'; import DeviceOs from './DeviceOs'; import DeviceApplications from './DeviceApplications'; +import DeviceSystemdUnits from './DeviceSystemdUnits'; import StatusContent from './DeviceDetailsTabContent/StatusContent'; import SystemResourcesContent from './DeviceDetailsTabContent/SystemResourcesContent'; @@ -157,7 +158,10 @@ const EnrolledDeviceDetails = ({ - + + + + ); @@ -221,7 +225,7 @@ const DecommissionedDeviceDetails = ({ device, children }: React.PropsWithChildr - + ); diff --git a/libs/ui-components/src/components/Device/DeviceDetails/DeviceSystemdUnits.tsx b/libs/ui-components/src/components/Device/DeviceDetails/DeviceSystemdUnits.tsx new file mode 100644 index 000000000..421c38021 --- /dev/null +++ b/libs/ui-components/src/components/Device/DeviceDetails/DeviceSystemdUnits.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { CardTitle, Flex, FlexItem } from '@patternfly/react-core'; + +import { Device } from '@flightctl/types'; +import { useTranslation } from '../../../hooks/useTranslation'; +import SystemdUnitsTable from '../../DetailsPage/Tables/SystemdUnitsTable'; +import DetailsPageCard, { DetailsPageCardBody } from '../../DetailsPage/DetailsPageCard'; + +type DeviceSystemdUnitsProps = { + device: Required; +}; + +const DeviceSystemdUnits = ({ device }: DeviceSystemdUnitsProps) => { + const { t } = useTranslation(); + + return ( + + + + {t('System services')} + + + + + + + ); +}; + +export default DeviceSystemdUnits; diff --git a/libs/ui-components/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx b/libs/ui-components/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx index 4c65cae4d..e592bfe25 100644 --- a/libs/ui-components/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx +++ b/libs/ui-components/src/components/Device/EditDeviceWizard/EditDeviceWizard.tsx @@ -28,7 +28,12 @@ import DeviceTemplateStep, { deviceTemplateStepId, isDeviceTemplateStepValid } f import DeviceUpdateStep, { deviceUpdatePolicyStepId, isUpdatePolicyStepValid } from './steps/DeviceUpdateStep'; import ReviewDeviceStep, { reviewDeviceStepId } from './steps/ReviewDeviceStep'; import { getDevicePatches, getValidationSchema } from './utils'; -import { getApplicationValues, getConfigTemplatesValues, hasMicroshiftRegistrationConfig } from './deviceSpecUtils'; +import { + getApplicationValues, + getConfigTemplatesValues, + getSystemdUnitsValues, + hasMicroshiftRegistrationConfig, +} from './deviceSpecUtils'; import { useFetch } from '../../../hooks/useFetch'; import { useEditDevice } from './useEditDevice'; import EditDeviceWizardNav from './EditDeviceWizardNav'; @@ -83,7 +88,7 @@ const EditDeviceWizard = () => { configTemplates: getConfigTemplatesValues(device.spec, registerMicroShift), fleetMatch: '', // Initially this is always a fleetless device applications: getApplicationValues(device.spec), - systemdUnits: [], + systemdUnits: getSystemdUnitsValues(device.spec), registerMicroShift, updatePolicy: { ...updatePolicyValues, diff --git a/libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts b/libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts index eec85c9cd..e46d1a80f 100644 --- a/libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts +++ b/libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts @@ -25,6 +25,7 @@ import { InlineConfigTemplate, KubeSecretTemplate, SpecConfigTemplate, + SystemdUnitFormValue, isGitConfigTemplate, isGitProviderSpec, isHttpConfigTemplate, @@ -409,6 +410,15 @@ export const getApplicationValues = (deviceSpec?: DeviceSpec): AppForm[] => { }); }; +export const getSystemdUnitsValues = (deviceSpec?: DeviceSpec): SystemdUnitFormValue[] => { + return ( + deviceSpec?.systemd?.matchPatterns?.map((pattern) => ({ + pattern, + exists: true, + })) || [] + ); +}; + export const getConfigTemplatesValues = (deviceSpec?: DeviceSpec, registerMicroShift?: boolean) => { const deviceConfig = registerMicroShift ? deviceSpec?.config?.filter((c) => !isConfigACMCrd(c) && !isConfigACMImport(c) && !isMicroshiftRegistrationHook(c)) diff --git a/libs/ui-components/src/components/Device/EditDeviceWizard/steps/DeviceTemplateStep.tsx b/libs/ui-components/src/components/Device/EditDeviceWizard/steps/DeviceTemplateStep.tsx index df627e1ba..e39b56a06 100644 --- a/libs/ui-components/src/components/Device/EditDeviceWizard/steps/DeviceTemplateStep.tsx +++ b/libs/ui-components/src/components/Device/EditDeviceWizard/steps/DeviceTemplateStep.tsx @@ -145,7 +145,7 @@ const DeviceTemplateStep = ({ isFleet, isReadOnly }: { isFleet: boolean; isReadO - {isFleet && } + {appType === FlightCtlApp.OCP && } diff --git a/libs/ui-components/src/components/Device/EditDeviceWizard/utils.ts b/libs/ui-components/src/components/Device/EditDeviceWizard/utils.ts index b9faf97e0..d42f5648e 100644 --- a/libs/ui-components/src/components/Device/EditDeviceWizard/utils.ts +++ b/libs/ui-components/src/components/Device/EditDeviceWizard/utils.ts @@ -9,7 +9,12 @@ import { validOsImage, validUpdatePolicySchema, } from '../../form/validations'; -import { appendJSONPatch, getDeviceLabelPatches, getUpdatePolicyPatches } from '../../../utils/patch'; +import { + appendJSONPatch, + getDeviceLabelPatches, + getStringListPatches, + getUpdatePolicyPatches, +} from '../../../utils/patch'; import { Device, PatchRequest } from '@flightctl/types'; import { EditDeviceFormValues, UpdatePolicyForm } from './../../../types/deviceSpec'; import { @@ -84,6 +89,15 @@ export const getDevicePatches = (currentDevice: Device, updatedDevice: EditDevic const appPatches = getApplicationPatches('/spec', currentDevice.spec?.applications || [], updatedDevice.applications); allPatches = allPatches.concat(appPatches); + // Systemd services + const systemdUnitPatches = getStringListPatches( + '/spec/systemd', + currentDevice.spec?.systemd?.matchPatterns || [], + updatedDevice.systemdUnits.map((unit) => unit.pattern), + (list) => ({ matchPatterns: list }), + ); + allPatches = allPatches.concat(systemdUnitPatches); + // Updates const updatesPatches = getUpdatePolicyPatches('/spec/updatePolicy', currentDevice.spec?.updatePolicy, { ...updatedDevice.updatePolicy, diff --git a/libs/ui-components/src/components/Fleet/CreateFleet/utils.ts b/libs/ui-components/src/components/Fleet/CreateFleet/utils.ts index 3a96aa885..e5fc5b618 100644 --- a/libs/ui-components/src/components/Fleet/CreateFleet/utils.ts +++ b/libs/ui-components/src/components/Fleet/CreateFleet/utils.ts @@ -32,6 +32,7 @@ import { getApplicationValues, getConfigTemplatesValues, getDeviceSpecConfigPatches, + getSystemdUnitsValues, hasMicroshiftRegistrationConfig, toAPIApplication, } from '../../Device/EditDeviceWizard/deviceSpecUtils'; @@ -236,10 +237,7 @@ export const getInitialValues = (fleet?: Fleet): FleetFormValues => { osImage: fleet.spec.template.spec.os?.image || '', configTemplates: getConfigTemplatesValues(fleet.spec.template.spec, registerMicroShift), applications: getApplicationValues(fleet.spec.template.spec), - systemdUnits: (fleet.spec.template.spec.systemd?.matchPatterns || []).map((p) => ({ - pattern: p, - exists: true, - })), + systemdUnits: getSystemdUnitsValues(fleet.spec.template.spec), registerMicroShift, rolloutPolicy, disruptionBudget, From 3f90af4a8522aa5c36cf9aed460a2dc6be4245b6 Mon Sep 17 00:00:00 2001 From: Celia Amador Date: Mon, 17 Nov 2025 16:33:18 +0100 Subject: [PATCH 2/2] Apply latest UX design --- libs/i18n/locales/en/translation.json | 4 +- .../DetailsPage/Tables/SystemdUnitsTable.tsx | 43 +++++++++++-------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/libs/i18n/locales/en/translation.json b/libs/i18n/locales/en/translation.json index 11475bb76..cdb7f36ad 100644 --- a/libs/i18n/locales/en/translation.json +++ b/libs/i18n/locales/en/translation.json @@ -125,10 +125,8 @@ "Reason": "Reason", "Message": "Message", "No conditions found": "No conditions found", - "Enable state": "Enable state", + "Enable": "Enable", "Load state": "Load state", - "Active state": "Active state", - "Sub state": "Sub state", "System services table": "System services table", "No system services found": "No system services found", "System services can be configured via the device specification": "System services can be configured via the device specification", diff --git a/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx b/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx index 876e0141d..75d0989bf 100644 --- a/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx +++ b/libs/ui-components/src/components/DetailsPage/Tables/SystemdUnitsTable.tsx @@ -5,19 +5,30 @@ import { CogIcon } from '@patternfly/react-icons/dist/js/icons/cog-icon'; import { ClockIcon } from '@patternfly/react-icons/dist/js/icons/clock-icon'; import { SystemdUnitStatus } from '@flightctl/types'; +import FolderIcon from '@patternfly/react-icons/dist/js/icons/folder-icon'; +import { DatabaseIcon } from '@patternfly/react-icons/dist/js/icons/database-icon'; +import { NetworkIcon } from '@patternfly/react-icons/dist/js/icons/network-icon'; +import { ConnectedIcon } from '@patternfly/react-icons/dist/js/icons/connected-icon'; import { useTranslation } from '../../../hooks/useTranslation'; -const serviceRegex = /\.service$/; -const timerRegex = /\.timer$/; +const unitTypeIconMap: Record> = { + service: CogIcon, + timer: ClockIcon, + socket: ConnectedIcon, + target: NetworkIcon, + mount: DatabaseIcon, + path: FolderIcon, +}; const SystemdUnitStatusIcon = ({ unitName }: { unitName: string }) => { - if (serviceRegex.test(unitName)) { - return ; - } - if (timerRegex.test(unitName)) { - return ; + const unitType = unitName.split('.').pop(); + const IconComponent = unitType ? unitTypeIconMap[unitType] : null; + + if (!IconComponent) { + return null; } - return null; + + return ; }; type SystemdUnitsTableProps = { @@ -32,7 +43,7 @@ const SystemdUnitRow = ({ unitStatus }: { unitStatus: SystemdUnitStatus }) => { {unitStatus.unit} - + @@ -42,14 +53,9 @@ const SystemdUnitRow = ({ unitStatus }: { unitStatus: SystemdUnitStatus }) => { {unitStatus.loadState} - - - - + @@ -66,10 +72,9 @@ const SystemdUnitsTable = ({ systemdUnitsStatus }: SystemdUnitsTableProps) => { {t('Name')} - {t('Enable state')} + {t('Enable')} {t('Load state')} - {t('Active state')} - {t('Sub state')} + {t('Status')}