diff --git a/public/locales/cs/translation.json b/public/locales/cs/translation.json index 23ece437..beeb2c0a 100644 --- a/public/locales/cs/translation.json +++ b/public/locales/cs/translation.json @@ -74,6 +74,10 @@ "description": "Intenzita poruch nastavená manuálně týmem AVA na základě zkušeného inženýrského úsudku." } }, + "faultEventMessage": { + "outOfSyncValue": "Hodnota je zastaralá!", + "requirementViolated": "Vypočtená intenzita poruch je větší, než je požadováno!" + }, "faultTreeOverviewTable": { "name": "Jméno", "aircraftType": "Typ systému", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index a5c2de43..e081b266 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -74,6 +74,10 @@ "description": "Failure rate manually set by AVA team based on experienced engineering judgment." } }, + "faultEventMessage": { + "outOfSyncValue": "The value is outdated!", + "requirementViolated": "Calculated failure rate is bigger than required!" + }, "faultTreeOverviewTable": { "name": "Name", "aircraftType": "System type", diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx new file mode 100644 index 00000000..d01816c4 --- /dev/null +++ b/src/components/Icons.tsx @@ -0,0 +1,15 @@ +import { SyncProblem, Warning } from "@mui/icons-material"; +import { Tooltip } from "@mui/material"; +import React from "react"; + +export const warnIcon = (message: string) => { + return iconWithMessage(, message); +}; + +export const syncProblemIcon = (message: string) => { + return iconWithMessage(, message); +}; + +export const iconWithMessage = (icon, message: string) => { + return {icon}; +}; diff --git a/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.styles.tsx b/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.styles.tsx index 3998d5d3..f3cdf0f3 100644 --- a/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.styles.tsx +++ b/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.styles.tsx @@ -33,9 +33,9 @@ const useStyles = makeStyles()((theme: Theme) => ({ color: theme.main.grey, }, outdated: { - color: "red", + color: theme.main.orange, "&.Mui-checked": { - color: theme.main.red, + color: theme.main.orange, }, }, divider: { diff --git a/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.tsx b/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.tsx index eea87546..8a945b55 100644 --- a/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.tsx +++ b/src/components/editor/faultTree/menu/faultEvent/FaultEventMenu.tsx @@ -28,6 +28,7 @@ import { useSelectedSystemSummaries } from "@hooks/useSelectedSystemSummaries"; import { useForm } from "react-hook-form"; import UnsavedChangesDialog from "./UnsavedChangesDialog"; import { useAppBar } from "@contexts/AppBarContext"; +import { warnIcon } from "@components/Icons"; interface Props { selectedShapeToolData?: FaultEvent; @@ -315,6 +316,11 @@ const FaultEventMenu = ({ selectedShapeToolData, onEventUpdated, refreshTree, ro return ; }; + const violatesRequirement = + shapeToolData?.probability && getRequiredFailureRate() && shapeToolData.probability > getRequiredFailureRate(); + + const requiredFailureRateStatusColor = violatesRequirement ? theme.main.red : theme.main.black; + return ( {shapeToolData && ( @@ -340,11 +346,12 @@ const FaultEventMenu = ({ selectedShapeToolData, onEventUpdated, refreshTree, ro )} {getRequiredFailureRate() && ( - + {t("faultEventMenu.requiredFailureRate")}: {getRequiredFailureRate().toExponential(2)} + {violatesRequirement && warnIcon(t("faultEventMessage.requirementViolated"))} )} @@ -372,11 +379,12 @@ const FaultEventMenu = ({ selectedShapeToolData, onEventUpdated, refreshTree, ro )} {getRequiredFailureRate() && ( - + {t("faultEventMenu.requiredFailureRate")}: {getRequiredFailureRate().toExponential(2)} + {violatesRequirement && warnIcon(t("faultEventMessage.requirementViolated"))} )} diff --git a/src/components/table/FaultTreeTableBody.tsx b/src/components/table/FaultTreeTableBody.tsx index c9678fc5..7f89d66e 100644 --- a/src/components/table/FaultTreeTableBody.tsx +++ b/src/components/table/FaultTreeTableBody.tsx @@ -1,5 +1,5 @@ import React, { FC } from "react"; -import { TableRow, TableCell, Button, Box, Tooltip, Typography } from "@mui/material"; +import { TableRow, TableCell, Button, Box, Tooltip, Typography, useTheme, Stack } from "@mui/material"; import MoreVertIcon from "@mui/icons-material/MoreVert"; import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; @@ -10,6 +10,7 @@ import { findByIri, formatDate } from "@utils/utils"; import { ROUTES, Status } from "@utils/constants"; import { useSelectedSystemSummaries } from "@hooks/useSelectedSystemSummaries"; import { useSystems } from "@hooks/useSystems"; +import { syncProblemIcon, warnIcon } from "@components/Icons"; interface FaultTreeTableBodyProps { faultTrees: FaultTree[]; @@ -18,6 +19,7 @@ interface FaultTreeTableBodyProps { const FaultTreeTableBody: FC = ({ faultTrees, handleFaultTreeContextMenu }) => { const navigate = useNavigate(); + const theme = useTheme(); const { t } = useTranslation(); const { classes } = useStyles(); @@ -29,28 +31,46 @@ const FaultTreeTableBody: FC = ({ faultTrees, handleFau navigate(routePath); }; - const failureRate = (fr: number) => ( - - {fr?.toExponential(2)} - + const failureRate = (fr: number, icon = null) => ( + + + {fr?.toExponential(2)} + + {!!icon && icon} + ); return ( <> {faultTrees.map((faultTree, rowIndex) => { const routePath = ROUTES.FTA + `/${extractFragment(faultTree.iri)}`; - const statusColor = faultTree?.status !== Status.OK ? "red" : "black"; + const isSynced = faultTree?.status === Status.OK; + const syncStatusColor = isSynced ? theme.synchronized.color : theme.notSynchronized.color; + const violatedRequirement = + faultTree?.requiredFailureRate && + faultTree?.calculatedFailureRate && + faultTree?.calculatedFailureRate > faultTree?.requiredFailureRate; + const violatedRequirementStatusColor = violatedRequirement ? theme.main.red : theme.main.black; + const editor = faultTree?.editor || faultTree?.creator; return ( {faultTree.name} {faultTree?.system?.name} {faultTree?.subSystem?.name} - - {failureRate(faultTree?.calculatedFailureRate)} + + {failureRate( + faultTree?.calculatedFailureRate, + !isSynced && faultTree?.calculatedFailureRate && syncProblemIcon(t("faultEventMessage.outOfSyncValue")), + )} {failureRate(faultTree?.fhaBasedFailureRate)} - {failureRate(faultTree?.requiredFailureRate)} + + {failureRate( + faultTree?.requiredFailureRate, + violatedRequirement && warnIcon(t("faultEventMessage.requirementViolated")), + )} + {formatDate(faultTree?.modified)} {formatDate(faultTree?.created)} {editor?.username} diff --git a/src/styles/App.styles.declarations.tsx b/src/styles/App.styles.declarations.tsx index 5527e646..4e2e4801 100644 --- a/src/styles/App.styles.declarations.tsx +++ b/src/styles/App.styles.declarations.tsx @@ -39,6 +39,7 @@ declare module "@mui/material/styles" { black: string; grey: string; red: string; + orange: string; notSynchronized?: { color: COLOR; }; diff --git a/src/styles/App.styles.tsx b/src/styles/App.styles.tsx index 00e3dae4..d099f0a6 100644 --- a/src/styles/App.styles.tsx +++ b/src/styles/App.styles.tsx @@ -38,11 +38,12 @@ export const appTheme = createCustomMuiTheme({ black: "#000000", grey: "#808080", red: "#FF0000", + orange: "#FF9F00", }, notSynchronized: { - color: "red", + color: "#FF9F00", }, synchronized: { - color: "black", + color: "#000000", }, });