@kartverket/backstage-plugin-risk-scorecard 3.3.4 → 3.3.10

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.
@@ -39,6 +39,7 @@ function RiScInfo({ riScWithMetadata, edit }) {
39
39
  variant: "standard",
40
40
  value: selectedRiSc?.id ?? "",
41
41
  onChange: (e) => selectRiSc(e.target.value),
42
+ style: { width: "100%" },
42
43
  children: riScs.map((riSc) => /* @__PURE__ */ jsx(MenuItem, { value: riSc.id, children: /* @__PURE__ */ jsx(ListItemText, { primary: riSc.content.title }) }, riSc.id)) ?? []
43
44
  }
44
45
  )
@@ -1 +1 @@
1
- {"version":3,"file":"RiScInfo.esm.js","sources":["../../../src/components/riScInfo/RiScInfo.tsx"],"sourcesContent":["import { RiScWithMetadata } from '../../utils/types';\nimport {\n Box,\n Grid,\n Typography,\n Select,\n MenuItem,\n ListItemText,\n} from '@material-ui/core';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { pluginRiScTranslationRef } from '../../utils/translations.ts';\nimport { RiScStatusComponent } from './riScStatus/RiScStatusComponent';\nimport { InfoCard } from '@backstage/core-components';\nimport EditButton from '../common/EditButton';\nimport { useRiScs } from '../../contexts/RiScContext';\nimport { Markdown } from '../common/Markdown';\n\ninterface RiScInfoProps {\n riScWithMetadata: RiScWithMetadata;\n edit: () => void;\n}\n\nexport function RiScInfo({ riScWithMetadata, edit }: RiScInfoProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n const { approveRiSc, riScs, selectedRiSc, selectRiSc } = useRiScs();\n\n return (\n <Grid container>\n <Grid\n item\n xs={12}\n sm={6}\n md={6}\n style={{\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n <InfoCard>\n <Box sx={{ mb: 2 }}>\n {riScs !== null && riScs.length !== 0 && (\n <>\n <Typography\n variant=\"h6\"\n style={{ fontSize: 16, marginBottom: 1 }}\n >\n {t('contentHeader.multipleRiScs')}\n </Typography>\n <Select\n variant=\"standard\"\n value={selectedRiSc?.id ?? ''}\n onChange={e => selectRiSc(e.target.value as string)}\n >\n {riScs.map(riSc => (\n <MenuItem key={riSc.id} value={riSc.id}>\n <ListItemText primary={riSc.content.title} />\n </MenuItem>\n )) ?? []}\n </Select>\n </>\n )}\n </Box>\n <Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }}\n >\n <Typography variant=\"h5\">\n {riScWithMetadata.content.title}\n </Typography>\n <EditButton onClick={edit} />\n </Box>\n <Markdown description={riScWithMetadata.content.scope} />\n </InfoCard>\n </Grid>\n <Grid item xs={12} sm={6} md={6}>\n <RiScStatusComponent\n selectedRiSc={riScWithMetadata}\n publishRiScFn={approveRiSc}\n />\n </Grid>\n </Grid>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AAsBO,SAAS,QAAS,CAAA,EAAE,gBAAkB,EAAA,IAAA,EAAuB,EAAA;AAClE,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,wBAAwB,CAAA;AACxD,EAAA,MAAM,EAAE,WAAa,EAAA,KAAA,EAAO,YAAc,EAAA,UAAA,KAAe,QAAS,EAAA;AAElE,EACE,uBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,SAAA,EAAS,IACb,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,IAAI,EAAA,IAAA;AAAA,QACJ,EAAI,EAAA,EAAA;AAAA,QACJ,EAAI,EAAA,CAAA;AAAA,QACJ,EAAI,EAAA,CAAA;AAAA,QACJ,KAAO,EAAA;AAAA,UACL,OAAS,EAAA,MAAA;AAAA,UACT,aAAe,EAAA;AAAA,SACjB;AAAA,QAEA,+BAAC,QACC,EAAA,EAAA,QAAA,EAAA;AAAA,0BAAC,GAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,EAAE,EAAI,EAAA,CAAA,EACZ,EAAA,QAAA,EAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,CAAM,MAAW,KAAA,CAAA,oBAEhC,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,UAAA;AAAA,cAAA;AAAA,gBACC,OAAQ,EAAA,IAAA;AAAA,gBACR,KAAO,EAAA,EAAE,QAAU,EAAA,EAAA,EAAI,cAAc,CAAE,EAAA;AAAA,gBAEtC,YAAE,6BAA6B;AAAA;AAAA,aAClC;AAAA,4BACA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,OAAQ,EAAA,UAAA;AAAA,gBACR,KAAA,EAAO,cAAc,EAAM,IAAA,EAAA;AAAA,gBAC3B,QAAU,EAAA,CAAA,CAAA,KAAK,UAAW,CAAA,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,gBAEjD,gBAAM,GAAI,CAAA,CAAA,IAAA,yBACR,QAAuB,EAAA,EAAA,KAAA,EAAO,KAAK,EAClC,EAAA,QAAA,kBAAA,GAAA,CAAC,gBAAa,OAAS,EAAA,IAAA,CAAK,QAAQ,KAAO,EAAA,CAAA,EAAA,EAD9B,KAAK,EAEpB,CACD,KAAK;AAAC;AAAA;AACT,WAAA,EACF,CAEJ,EAAA,CAAA;AAAA,0BACA,IAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cACC,KAAO,EAAA;AAAA,gBACL,OAAS,EAAA,MAAA;AAAA,gBACT,UAAY,EAAA,QAAA;AAAA,gBACZ,cAAgB,EAAA;AAAA,eAClB;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,IACjB,EAAA,QAAA,EAAA,gBAAA,CAAiB,QAAQ,KAC5B,EAAA,CAAA;AAAA,gCACA,GAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAS,IAAM,EAAA;AAAA;AAAA;AAAA,WAC7B;AAAA,0BACC,GAAA,CAAA,QAAA,EAAA,EAAS,WAAa,EAAA,gBAAA,CAAiB,QAAQ,KAAO,EAAA;AAAA,SACzD,EAAA;AAAA;AAAA,KACF;AAAA,oBACA,GAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAC,IAAI,EAAI,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,CAC5B,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,YAAc,EAAA,gBAAA;AAAA,QACd,aAAe,EAAA;AAAA;AAAA,KAEnB,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"RiScInfo.esm.js","sources":["../../../src/components/riScInfo/RiScInfo.tsx"],"sourcesContent":["import { RiScWithMetadata } from '../../utils/types';\nimport {\n Box,\n Grid,\n Typography,\n Select,\n MenuItem,\n ListItemText,\n} from '@material-ui/core';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { pluginRiScTranslationRef } from '../../utils/translations.ts';\nimport { RiScStatusComponent } from './riScStatus/RiScStatusComponent';\nimport { InfoCard } from '@backstage/core-components';\nimport EditButton from '../common/EditButton';\nimport { useRiScs } from '../../contexts/RiScContext';\nimport { Markdown } from '../common/Markdown';\n\ninterface RiScInfoProps {\n riScWithMetadata: RiScWithMetadata;\n edit: () => void;\n}\n\nexport function RiScInfo({ riScWithMetadata, edit }: RiScInfoProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n const { approveRiSc, riScs, selectedRiSc, selectRiSc } = useRiScs();\n\n return (\n <Grid container>\n <Grid\n item\n xs={12}\n sm={6}\n md={6}\n style={{\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n <InfoCard>\n <Box sx={{ mb: 2 }}>\n {riScs !== null && riScs.length !== 0 && (\n <>\n <Typography\n variant=\"h6\"\n style={{ fontSize: 16, marginBottom: 1 }}\n >\n {t('contentHeader.multipleRiScs')}\n </Typography>\n <Select\n variant=\"standard\"\n value={selectedRiSc?.id ?? ''}\n onChange={e => selectRiSc(e.target.value as string)}\n style={{ width: '100%' }}\n >\n {riScs.map(riSc => (\n <MenuItem key={riSc.id} value={riSc.id}>\n <ListItemText primary={riSc.content.title} />\n </MenuItem>\n )) ?? []}\n </Select>\n </>\n )}\n </Box>\n <Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n }}\n >\n <Typography variant=\"h5\">\n {riScWithMetadata.content.title}\n </Typography>\n <EditButton onClick={edit} />\n </Box>\n <Markdown description={riScWithMetadata.content.scope} />\n </InfoCard>\n </Grid>\n <Grid item xs={12} sm={6} md={6}>\n <RiScStatusComponent\n selectedRiSc={riScWithMetadata}\n publishRiScFn={approveRiSc}\n />\n </Grid>\n </Grid>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@ import { useScenario } from '../../../contexts/ScenarioContext.esm.js';
17
17
  import { ActionStatusOptions } from '../../../utils/constants.esm.js';
18
18
  import { useIsMounted } from '../../../utils/hooks.esm.js';
19
19
  import { pluginRiScTranslationRef } from '../../../utils/translations.esm.js';
20
- import { getTranslatedActionStatus, formatDate, actionStatusOptionsToTranslationKeys, calculateDaysSince, calculateUpdatedStatus, UpdatedStatusEnum, deleteAction } from '../../../utils/utilityfunctions.esm.js';
20
+ import { getTranslatedActionStatus, formatDate, getActionStatusStyle, getActionStatusColor, actionStatusOptionsToTranslationKeys, calculateDaysSince, calculateUpdatedStatus, UpdatedStatusEnum, deleteAction } from '../../../utils/utilityfunctions.esm.js';
21
21
  import { Markdown } from '../../common/Markdown.esm.js';
22
22
  import { label, body2, emptyState } from '../../common/typography.esm.js';
23
23
  import { ActionFormItem } from './ActionFormItem.esm.js';
@@ -30,7 +30,8 @@ function ActionBox({
30
30
  index,
31
31
  formMethods,
32
32
  remove,
33
- onSubmit
33
+ onSubmit,
34
+ setCurrentUpdatedActionIDs
34
35
  }) {
35
36
  const { t } = useTranslationRef(pluginRiScTranslationRef);
36
37
  const { isActionExpanded, toggleActionExpanded } = useScenario();
@@ -71,13 +72,7 @@ function ActionBox({
71
72
  function handleStatusChange(newStatus) {
72
73
  updateActionInScenario({ status: newStatus });
73
74
  }
74
- function refreshStatus() {
75
- if (isSameDay()) return;
76
- updateActionInScenario({});
77
- }
78
- function isSameDay() {
79
- const currentAction = scenario.actions.find((a) => a.ID === action.ID);
80
- const lastUpdated = currentAction?.lastUpdated;
75
+ function isToday(lastUpdated) {
81
76
  const today = /* @__PURE__ */ new Date();
82
77
  if (!lastUpdated) return false;
83
78
  const lastUpdatedParsed = typeof lastUpdated === "string" ? new Date(lastUpdated) : lastUpdated;
@@ -173,16 +168,8 @@ function ActionBox({
173
168
  DualButton,
174
169
  {
175
170
  propsCommon: {
176
- color: (() => {
177
- switch (action.status) {
178
- case ActionStatusOptions.OK:
179
- return "success";
180
- case ActionStatusOptions.NotOK:
181
- return "error";
182
- default:
183
- return "inherit";
184
- }
185
- })()
171
+ color: getActionStatusColor(action.status),
172
+ style: getActionStatusStyle(action.status)
186
173
  },
187
174
  propsLeft: {
188
175
  children: translatedActionStatus,
@@ -191,7 +178,16 @@ function ActionBox({
191
178
  propsRight: {
192
179
  startIcon: /* @__PURE__ */ jsx(Cached, {}),
193
180
  sx: { padding: "0 0 0 10px", minWidth: "30px" },
194
- onClick: () => refreshStatus()
181
+ onClick: () => {
182
+ if (isToday(action.lastUpdated ?? null)) return;
183
+ formMethods.setValue(
184
+ `actions.${index}.lastUpdated`,
185
+ /* @__PURE__ */ new Date()
186
+ );
187
+ setCurrentUpdatedActionIDs(
188
+ (prev) => prev.includes(action.ID) ? prev : [...prev, action.ID]
189
+ );
190
+ }
195
191
  }
196
192
  }
197
193
  ),
@@ -338,7 +334,8 @@ function Exclamations({
338
334
  ) });
339
335
  case UpdatedStatusEnum.OUTDATED:
340
336
  return /* @__PURE__ */ jsx(Tooltip, { title: t("rosStatus.updatedStatus.tooltip.OUTDATED"), children: /* @__PURE__ */ jsx(Box, { sx: { color: "#FF8B38", minWidth: "24px", textAlign: "right" }, children: /* @__PURE__ */ jsx(PriorityHigh, { sx: { marginRight: "-6px", marginLeft: "-6px" } }) }) });
341
- case (UpdatedStatusEnum.LITTLE_OUTDATED):
337
+ case UpdatedStatusEnum.UPDATED:
338
+ case UpdatedStatusEnum.LITTLE_OUTDATED:
342
339
  return /* @__PURE__ */ jsx(Box, { sx: { minWidth: "24px" } });
343
340
  default:
344
341
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBox.esm.js","sources":["../../../../src/components/scenarioDrawer/components/ActionBox.tsx"],"sourcesContent":["import { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Cached,\n Edit,\n ExpandLess,\n ExpandMore,\n PriorityHigh,\n} from '@mui/icons-material';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Link from '@mui/material/Link';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Typography from '@mui/material/Typography';\nimport { useEffect, useState } from 'react';\nimport { UseFieldArrayRemove, UseFormReturn } from 'react-hook-form';\nimport { useRiScs } from '../../../contexts/RiScContext';\nimport { useScenario } from '../../../contexts/ScenarioContext';\nimport { ActionStatusOptions } from '../../../utils/constants';\nimport { useIsMounted } from '../../../utils/hooks';\nimport { pluginRiScTranslationRef } from '../../../utils/translations';\nimport { Action, FormScenario, LastPublished } from '../../../utils/types';\nimport {\n actionStatusOptionsToTranslationKeys,\n calculateDaysSince,\n calculateUpdatedStatus,\n deleteAction,\n formatDate,\n UpdatedStatusEnum,\n getTranslatedActionStatus,\n} from '../../../utils/utilityfunctions';\nimport { Markdown } from '../../common/Markdown';\nimport { body2, emptyState, label } from '../../common/typography';\nimport { ActionFormItem } from './ActionFormItem';\nimport { DeleteActionConfirmation } from './DeleteConfirmation';\nimport { DualButton } from '../../common/DualButton';\nimport { Tooltip } from '@material-ui/core';\n\ninterface ActionBoxProps {\n action: Action;\n index: number;\n formMethods: UseFormReturn<FormScenario>;\n remove: UseFieldArrayRemove;\n onSubmit: () => void;\n}\n\nexport function ActionBox({\n action,\n index,\n formMethods,\n remove,\n onSubmit,\n}: ActionBoxProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n\n const { isActionExpanded, toggleActionExpanded } = useScenario();\n const isExpanded = isActionExpanded(action.ID);\n\n const [isEditing, setIsEditing] = useState<boolean>(false);\n const [deleteActionConfirmationIsOpen, setDeleteActionConfirmationIsOpen] =\n useState(false);\n\n const { updateStatus, selectedRiSc } = useRiScs();\n\n const { submitEditedScenarioToRiSc, mapFormScenarioToScenario, scenario } =\n useScenario();\n\n const isActionTitlePresent = action.title !== null && action.title !== '';\n\n /* @ts-ignore Because ts can't typecheck strings against our keys */\n const translatedActionStatus = getTranslatedActionStatus(action.status, t);\n\n const isMounted = useIsMounted();\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(anchorEl);\n\n function handleDeleteAction(): void {\n setDeleteActionConfirmationIsOpen(true);\n }\n\n function confirmDeleteAction(): void {\n deleteAction(remove, index, onSubmit);\n setDeleteActionConfirmationIsOpen(false);\n }\n\n function handleChipClick(event: React.MouseEvent<HTMLElement>) {\n setAnchorEl(event.currentTarget);\n }\n\n function handleMenuClose() {\n setAnchorEl(null);\n }\n\n const parsedDateTime = action.lastUpdated\n ? formatDate(action.lastUpdated)\n : t('scenarioDrawer.action.notUpdated');\n\n function updateActionInScenario(updates: Partial<Action>) {\n const updatedScenario = {\n ...scenario,\n actions: scenario.actions.map(a =>\n a.ID === action.ID ? { ...a, ...updates, lastUpdated: new Date() } : a,\n ),\n };\n\n submitEditedScenarioToRiSc(updatedScenario);\n if (isMounted()) handleMenuClose();\n }\n\n function handleStatusChange(newStatus: string) {\n updateActionInScenario({ status: newStatus });\n }\n\n function refreshStatus() {\n if (isSameDay()) return;\n updateActionInScenario({});\n }\n\n function isSameDay(): boolean {\n const currentAction = scenario.actions.find(a => a.ID === action.ID);\n const lastUpdated = currentAction?.lastUpdated;\n const today = new Date();\n\n if (!lastUpdated) return false;\n const lastUpdatedParsed =\n typeof lastUpdated === 'string' ? new Date(lastUpdated) : lastUpdated;\n\n return (\n lastUpdatedParsed.getDate() === today.getDate() &&\n lastUpdatedParsed.getMonth() === today.getMonth() &&\n lastUpdatedParsed.getFullYear() === today.getFullYear()\n );\n }\n\n useEffect(() => () => setAnchorEl(null), []);\n\n if (isEditing) {\n return (\n <>\n <ActionFormItem\n formMethods={formMethods}\n index={index}\n handleDelete={handleDeleteAction}\n showTitleNumber={false}\n remove={remove}\n />\n <Box display=\"flex\" gap={1}>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={formMethods.handleSubmit((data: FormScenario) => {\n submitEditedScenarioToRiSc(mapFormScenarioToScenario(data));\n })}\n disabled={!formMethods.formState.isDirty || updateStatus.isLoading}\n >\n {t('dictionary.save')}\n {updateStatus.isLoading && (\n <CircularProgress\n size={16}\n sx={{ marginLeft: 8, color: 'inherit' }}\n />\n )}\n </Button>\n\n <Button onClick={() => setIsEditing(false)}>\n {t('dictionary.cancel')}\n </Button>\n </Box>\n </>\n );\n }\n\n return (\n <Box>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n gap: 1,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n cursor: 'pointer',\n width: '100%',\n }}\n onClick={() => toggleActionExpanded(action.ID)}\n >\n <IconButton>\n {isExpanded ? <ExpandLess /> : <ExpandMore />}\n </IconButton>\n <Typography\n sx={{\n fontSize: '16px',\n fontWeight: 500,\n }}\n >\n {isActionTitlePresent\n ? action.title\n : `${t('dictionary.measure')} ${index + 1}`}\n </Typography>\n </Box>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n gap: 2,\n alignItems: 'center',\n }}\n >\n <DualButton\n propsCommon={{\n color: (() => {\n switch (action.status) {\n case ActionStatusOptions.OK:\n return 'success';\n case ActionStatusOptions.NotOK:\n return 'error';\n default:\n return 'inherit';\n }\n })(),\n }}\n propsLeft={{\n children: translatedActionStatus,\n onClick: handleChipClick,\n }}\n propsRight={{\n startIcon: <Cached />,\n sx: { padding: '0 0 0 10px', minWidth: '30px' },\n onClick: () => refreshStatus(),\n }}\n />\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleMenuClose}\n onClick={handleMenuClose}\n >\n {Object.values(ActionStatusOptions).map(value => (\n <MenuItem\n key={value}\n onClick={() => handleStatusChange(value)}\n selected={value === action.status}\n >\n {\n /* @ts-ignore Because ts can't typecheck strings against our keys */\n t(\n actionStatusOptionsToTranslationKeys[\n value as ActionStatusOptions\n ],\n )\n }\n </MenuItem>\n ))}\n </Menu>\n <Box\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n <Typography>{t('scenarioDrawer.action.lastUpdated')}</Typography>\n <Typography>{parsedDateTime}</Typography>\n </Box>\n <Exclamations\n action={action}\n lastPublished={selectedRiSc?.lastPublished}\n />\n </Box>\n <IconButton onClick={handleDeleteAction}>\n <DeleteIcon />\n </IconButton>\n </Box>\n\n <Collapse in={isExpanded} sx={{ marginTop: 1 }}>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n }}\n >\n <Typography sx={{ ...label, marginTop: 1 }}>\n {t('dictionary.description')}\n </Typography>\n <IconButton\n sx={{\n marginLeft: 'auto',\n transition: 'opacity 300ms ease-in',\n }}\n onClick={() => setIsEditing(!isEditing)}\n >\n <Edit />\n </IconButton>\n </Box>\n <Markdown description={action.description} />\n\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'end',\n marginTop: '16px',\n }}\n >\n <Box>\n <Typography sx={label}>{t('dictionary.url')}</Typography>\n {action.url ? (\n <Link\n sx={{\n ...body2,\n wordBreak: 'break-all',\n }}\n target=\"_blank\"\n rel=\"noreferrer\"\n href={\n action.url.startsWith('http') ? action.url : `//${action.url}`\n }\n >\n {action.url}\n </Link>\n ) : (\n <Typography sx={emptyState}>\n {t('dictionary.emptyField', {\n field: t('dictionary.url').toLowerCase(),\n })}\n </Typography>\n )}\n </Box>\n </Box>\n </Collapse>\n\n <DeleteActionConfirmation\n isOpen={deleteActionConfirmationIsOpen}\n setIsOpen={setDeleteActionConfirmationIsOpen}\n onConfirm={confirmDeleteAction}\n />\n </Box>\n );\n}\n\nfunction Exclamations({\n action,\n lastPublished,\n}: {\n action: Action;\n lastPublished?: LastPublished;\n}) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n const daysSinceLastUpdate = action.lastUpdated\n ? calculateDaysSince(new Date(action.lastUpdated))\n : null;\n const status = calculateUpdatedStatus(\n daysSinceLastUpdate,\n lastPublished?.numberOfCommits || null,\n );\n\n switch (status) {\n case UpdatedStatusEnum.VERY_OUTDATED:\n return (\n <Tooltip title={t('rosStatus.updatedStatus.tooltip.VERY_OUTDATED')}>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n color: '#FF4444',\n }}\n >\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n </Box>\n </Tooltip>\n );\n case UpdatedStatusEnum.OUTDATED:\n return (\n <Tooltip title={t('rosStatus.updatedStatus.tooltip.OUTDATED')}>\n <Box sx={{ color: '#FF8B38', minWidth: '24px', textAlign: 'right' }}>\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n </Box>\n </Tooltip>\n );\n case (UpdatedStatusEnum.UPDATED, UpdatedStatusEnum.LITTLE_OUTDATED):\n return <Box sx={{ minWidth: '24px' }} />;\n default:\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ActionBox.esm.js","sources":["../../../../src/components/scenarioDrawer/components/ActionBox.tsx"],"sourcesContent":["import { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Cached,\n Edit,\n ExpandLess,\n ExpandMore,\n PriorityHigh,\n} from '@mui/icons-material';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Link from '@mui/material/Link';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Typography from '@mui/material/Typography';\nimport { useEffect, useState } from 'react';\nimport { UseFieldArrayRemove, UseFormReturn } from 'react-hook-form';\nimport { useRiScs } from '../../../contexts/RiScContext';\nimport { useScenario } from '../../../contexts/ScenarioContext';\nimport { ActionStatusOptions } from '../../../utils/constants';\nimport { useIsMounted } from '../../../utils/hooks';\nimport { pluginRiScTranslationRef } from '../../../utils/translations';\nimport { Action, FormScenario, LastPublished } from '../../../utils/types';\nimport {\n actionStatusOptionsToTranslationKeys,\n calculateDaysSince,\n calculateUpdatedStatus,\n deleteAction,\n formatDate,\n UpdatedStatusEnum,\n getTranslatedActionStatus,\n getActionStatusColor,\n getActionStatusStyle,\n} from '../../../utils/utilityfunctions';\nimport { Markdown } from '../../common/Markdown';\nimport { body2, emptyState, label } from '../../common/typography';\nimport { ActionFormItem } from './ActionFormItem';\nimport { DeleteActionConfirmation } from './DeleteConfirmation';\nimport { DualButton } from '../../common/DualButton';\nimport { Tooltip } from '@material-ui/core';\n\ninterface ActionBoxProps {\n action: Action;\n index: number;\n formMethods: UseFormReturn<FormScenario>;\n remove: UseFieldArrayRemove;\n onSubmit: () => void;\n setCurrentUpdatedActionIDs: React.Dispatch<React.SetStateAction<string[]>>;\n}\n\nexport function ActionBox({\n action,\n index,\n formMethods,\n remove,\n onSubmit,\n setCurrentUpdatedActionIDs,\n}: ActionBoxProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n\n const { isActionExpanded, toggleActionExpanded } = useScenario();\n const isExpanded = isActionExpanded(action.ID);\n\n const [isEditing, setIsEditing] = useState<boolean>(false);\n const [deleteActionConfirmationIsOpen, setDeleteActionConfirmationIsOpen] =\n useState(false);\n\n const { updateStatus, selectedRiSc } = useRiScs();\n\n const { submitEditedScenarioToRiSc, mapFormScenarioToScenario, scenario } =\n useScenario();\n\n const isActionTitlePresent = action.title !== null && action.title !== '';\n\n /* @ts-ignore Because ts can't typecheck strings against our keys */\n const translatedActionStatus = getTranslatedActionStatus(action.status, t);\n\n const isMounted = useIsMounted();\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const open = Boolean(anchorEl);\n\n function handleDeleteAction(): void {\n setDeleteActionConfirmationIsOpen(true);\n }\n\n function confirmDeleteAction(): void {\n deleteAction(remove, index, onSubmit);\n setDeleteActionConfirmationIsOpen(false);\n }\n\n function handleChipClick(event: React.MouseEvent<HTMLElement>) {\n setAnchorEl(event.currentTarget);\n }\n\n function handleMenuClose() {\n setAnchorEl(null);\n }\n\n const parsedDateTime = action.lastUpdated\n ? formatDate(action.lastUpdated)\n : t('scenarioDrawer.action.notUpdated');\n\n function updateActionInScenario(updates: Partial<Action>) {\n const updatedScenario = {\n ...scenario,\n actions: scenario.actions.map(a =>\n a.ID === action.ID ? { ...a, ...updates, lastUpdated: new Date() } : a,\n ),\n };\n\n submitEditedScenarioToRiSc(updatedScenario);\n if (isMounted()) handleMenuClose();\n }\n\n function handleStatusChange(newStatus: string) {\n updateActionInScenario({ status: newStatus });\n }\n\n function isToday(lastUpdated: Date | null): boolean {\n const today = new Date();\n\n if (!lastUpdated) return false;\n const lastUpdatedParsed =\n typeof lastUpdated === 'string' ? new Date(lastUpdated) : lastUpdated;\n\n return (\n lastUpdatedParsed.getDate() === today.getDate() &&\n lastUpdatedParsed.getMonth() === today.getMonth() &&\n lastUpdatedParsed.getFullYear() === today.getFullYear()\n );\n }\n\n useEffect(() => () => setAnchorEl(null), []);\n\n if (isEditing) {\n return (\n <>\n <ActionFormItem\n formMethods={formMethods}\n index={index}\n handleDelete={handleDeleteAction}\n showTitleNumber={false}\n remove={remove}\n />\n <Box display=\"flex\" gap={1}>\n <Button\n color=\"primary\"\n variant=\"contained\"\n onClick={formMethods.handleSubmit((data: FormScenario) => {\n submitEditedScenarioToRiSc(mapFormScenarioToScenario(data));\n })}\n disabled={!formMethods.formState.isDirty || updateStatus.isLoading}\n >\n {t('dictionary.save')}\n {updateStatus.isLoading && (\n <CircularProgress\n size={16}\n sx={{ marginLeft: 8, color: 'inherit' }}\n />\n )}\n </Button>\n\n <Button onClick={() => setIsEditing(false)}>\n {t('dictionary.cancel')}\n </Button>\n </Box>\n </>\n );\n }\n\n return (\n <Box>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n gap: 1,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n cursor: 'pointer',\n width: '100%',\n }}\n onClick={() => toggleActionExpanded(action.ID)}\n >\n <IconButton>\n {isExpanded ? <ExpandLess /> : <ExpandMore />}\n </IconButton>\n <Typography\n sx={{\n fontSize: '16px',\n fontWeight: 500,\n }}\n >\n {isActionTitlePresent\n ? action.title\n : `${t('dictionary.measure')} ${index + 1}`}\n </Typography>\n </Box>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n gap: 2,\n alignItems: 'center',\n }}\n >\n <DualButton\n propsCommon={{\n color: getActionStatusColor(action.status),\n style: getActionStatusStyle(action.status),\n }}\n propsLeft={{\n children: translatedActionStatus,\n onClick: handleChipClick,\n }}\n propsRight={{\n startIcon: <Cached />,\n sx: { padding: '0 0 0 10px', minWidth: '30px' },\n onClick: () => {\n if (isToday(action.lastUpdated ?? null)) return;\n formMethods.setValue(\n `actions.${index}.lastUpdated`,\n new Date(),\n );\n setCurrentUpdatedActionIDs(prev =>\n prev.includes(action.ID) ? prev : [...prev, action.ID],\n );\n },\n }}\n />\n <Menu\n anchorEl={anchorEl}\n open={open}\n onClose={handleMenuClose}\n onClick={handleMenuClose}\n >\n {Object.values(ActionStatusOptions).map(value => (\n <MenuItem\n key={value}\n onClick={() => handleStatusChange(value)}\n selected={value === action.status}\n >\n {\n /* @ts-ignore Because ts can't typecheck strings against our keys */\n t(\n actionStatusOptionsToTranslationKeys[\n value as ActionStatusOptions\n ],\n )\n }\n </MenuItem>\n ))}\n </Menu>\n <Box\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n <Typography>{t('scenarioDrawer.action.lastUpdated')}</Typography>\n <Typography>{parsedDateTime}</Typography>\n </Box>\n <Exclamations\n action={action}\n lastPublished={selectedRiSc?.lastPublished}\n />\n </Box>\n <IconButton onClick={handleDeleteAction}>\n <DeleteIcon />\n </IconButton>\n </Box>\n\n <Collapse in={isExpanded} sx={{ marginTop: 1 }}>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n }}\n >\n <Typography sx={{ ...label, marginTop: 1 }}>\n {t('dictionary.description')}\n </Typography>\n <IconButton\n sx={{\n marginLeft: 'auto',\n transition: 'opacity 300ms ease-in',\n }}\n onClick={() => setIsEditing(!isEditing)}\n >\n <Edit />\n </IconButton>\n </Box>\n <Markdown description={action.description} />\n\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'end',\n marginTop: '16px',\n }}\n >\n <Box>\n <Typography sx={label}>{t('dictionary.url')}</Typography>\n {action.url ? (\n <Link\n sx={{\n ...body2,\n wordBreak: 'break-all',\n }}\n target=\"_blank\"\n rel=\"noreferrer\"\n href={\n action.url.startsWith('http') ? action.url : `//${action.url}`\n }\n >\n {action.url}\n </Link>\n ) : (\n <Typography sx={emptyState}>\n {t('dictionary.emptyField', {\n field: t('dictionary.url').toLowerCase(),\n })}\n </Typography>\n )}\n </Box>\n </Box>\n </Collapse>\n\n <DeleteActionConfirmation\n isOpen={deleteActionConfirmationIsOpen}\n setIsOpen={setDeleteActionConfirmationIsOpen}\n onConfirm={confirmDeleteAction}\n />\n </Box>\n );\n}\n\nfunction Exclamations({\n action,\n lastPublished,\n}: {\n action: Action;\n lastPublished?: LastPublished;\n}) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n const daysSinceLastUpdate = action.lastUpdated\n ? calculateDaysSince(new Date(action.lastUpdated))\n : null;\n const status = calculateUpdatedStatus(\n daysSinceLastUpdate,\n lastPublished?.numberOfCommits || null,\n );\n\n switch (status) {\n case UpdatedStatusEnum.VERY_OUTDATED:\n return (\n <Tooltip title={t('rosStatus.updatedStatus.tooltip.VERY_OUTDATED')}>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'row',\n color: '#FF4444',\n }}\n >\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n </Box>\n </Tooltip>\n );\n case UpdatedStatusEnum.OUTDATED:\n return (\n <Tooltip title={t('rosStatus.updatedStatus.tooltip.OUTDATED')}>\n <Box sx={{ color: '#FF8B38', minWidth: '24px', textAlign: 'right' }}>\n <PriorityHigh sx={{ marginRight: '-6px', marginLeft: '-6px' }} />\n </Box>\n </Tooltip>\n );\n case UpdatedStatusEnum.UPDATED:\n case UpdatedStatusEnum.LITTLE_OUTDATED:\n return <Box sx={{ minWidth: '24px' }} />;\n default:\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { ActionBox } from './ActionBox.esm.js';
3
- import { Fragment } from 'react';
3
+ import { useMemo, useState, Fragment } from 'react';
4
4
  import Paper from '@mui/material/Paper';
5
5
  import Typography from '@mui/material/Typography';
6
6
  import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
7
7
  import { pluginRiScTranslationRef } from '../../../utils/translations.esm.js';
8
- import { emptyAction } from '../../../contexts/ScenarioContext.esm.js';
8
+ import { useScenario, emptyAction } from '../../../contexts/ScenarioContext.esm.js';
9
9
  import { section } from '../scenarioDrawerComponents.esm.js';
10
10
  import { heading3, emptyState } from '../../common/typography.esm.js';
11
11
  import Divider from '@mui/material/Divider';
@@ -14,6 +14,8 @@ import { ActionFormItem } from './ActionFormItem.esm.js';
14
14
  import Button from '@mui/material/Button';
15
15
  import { AddCircle } from '@mui/icons-material';
16
16
  import Box from '@mui/material/Box';
17
+ import { ActionStatusOptions } from '../../../utils/constants.esm.js';
18
+ import { useDebounce } from '../../../utils/hooks.esm.js';
17
19
 
18
20
  function ActionsSection({
19
21
  formMethods,
@@ -27,6 +29,31 @@ function ActionsSection({
27
29
  name: "actions"
28
30
  });
29
31
  const currentActions = watch("actions");
32
+ const sortedActionsWithIndex = useMemo(() => {
33
+ if (!currentActions || currentActions.length === 0) return [];
34
+ return currentActions.map((action, originalIndex) => ({ action, originalIndex })).sort((a, b) => {
35
+ if (a.action.status === ActionStatusOptions.NotRelevant && b.action.status !== ActionStatusOptions.NotRelevant) {
36
+ return 1;
37
+ }
38
+ if (b.action.status === ActionStatusOptions.NotRelevant && a.action.status !== ActionStatusOptions.NotRelevant) {
39
+ return -1;
40
+ }
41
+ return 0;
42
+ });
43
+ }, [currentActions]);
44
+ const [currentUpdatedActionIDs, setCurrentUpdatedActionIDs] = useState([]);
45
+ const { submitEditedScenarioToRiSc, scenario } = useScenario();
46
+ useDebounce(currentUpdatedActionIDs, 6e3, (updatedIDs) => {
47
+ if (updatedIDs.length === 0) return;
48
+ const updatedScenario = {
49
+ ...scenario,
50
+ actions: scenario.actions.map(
51
+ (a) => updatedIDs.find((id) => id === a.ID) ? { ...a, lastUpdated: /* @__PURE__ */ new Date() } : a
52
+ )
53
+ };
54
+ submitEditedScenarioToRiSc(updatedScenario);
55
+ setCurrentUpdatedActionIDs([]);
56
+ });
30
57
  if (isEditing) {
31
58
  return /* @__PURE__ */ jsxs(Paper, { sx: section, children: [
32
59
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 2 }, children: [
@@ -57,19 +84,20 @@ function ActionsSection({
57
84
  }
58
85
  return /* @__PURE__ */ jsxs(Paper, { sx: section, children: [
59
86
  /* @__PURE__ */ jsx(Typography, { sx: heading3, children: t("dictionary.measures") }),
60
- fields.length > 0 ? fields.map((field, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
87
+ sortedActionsWithIndex.length > 0 ? sortedActionsWithIndex.map(({ action, originalIndex }) => /* @__PURE__ */ jsxs(Fragment, { children: [
61
88
  /* @__PURE__ */ jsx(Divider, {}),
62
89
  /* @__PURE__ */ jsx(
63
90
  ActionBox,
64
91
  {
65
- action: currentActions[index],
66
- index,
92
+ action,
93
+ index: originalIndex,
67
94
  formMethods,
68
95
  remove,
69
- onSubmit
96
+ onSubmit,
97
+ setCurrentUpdatedActionIDs
70
98
  }
71
99
  )
72
- ] }, field.id)) : /* @__PURE__ */ jsx(Typography, { sx: emptyState, children: t("dictionary.emptyField", {
100
+ ] }, fields[originalIndex].id)) : /* @__PURE__ */ jsx(Typography, { sx: emptyState, children: t("dictionary.emptyField", {
73
101
  field: t("dictionary.measures").toLowerCase()
74
102
  }) })
75
103
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"ActionsSection.esm.js","sources":["../../../../src/components/scenarioDrawer/components/ActionsSection.tsx"],"sourcesContent":["import { ActionBox } from './ActionBox';\nimport { Fragment } from 'react';\nimport Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { pluginRiScTranslationRef } from '../../../utils/translations';\nimport { emptyAction } from '../../../contexts/ScenarioContext';\nimport { section } from '../scenarioDrawerComponents';\nimport { emptyState, heading3 } from '../../common/typography';\nimport Divider from '@mui/material/Divider';\nimport { useFieldArray, UseFormReturn } from 'react-hook-form';\nimport { FormScenario } from '../../../utils/types';\nimport { ActionFormItem } from './ActionFormItem';\nimport Button from '@mui/material/Button';\nimport { AddCircle } from '@mui/icons-material';\nimport Box from '@mui/material/Box';\n\ntype ActionSectionProps = {\n formMethods: UseFormReturn<FormScenario>;\n isEditing: boolean;\n onSubmit: () => void;\n};\n\nexport function ActionsSection({\n formMethods,\n isEditing,\n onSubmit,\n}: ActionSectionProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n\n const { control, watch } = formMethods;\n const { fields, append, remove } = useFieldArray({\n control,\n name: 'actions',\n });\n\n const currentActions = watch('actions');\n\n if (isEditing) {\n return (\n <Paper sx={section}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={heading3}>{t('dictionary.measure')}</Typography>\n <Button\n startIcon={<AddCircle />}\n color=\"primary\"\n onClick={() => append(emptyAction())}\n >\n {t('scenarioDrawer.measureTab.addMeasureButton')}\n </Button>\n </Box>\n {fields.map((field, index) => (\n <Fragment key={field.id}>\n <Divider variant=\"fullWidth\" />\n <ActionFormItem\n key={index}\n formMethods={formMethods}\n index={index}\n remove={remove}\n />\n </Fragment>\n ))}\n </Paper>\n );\n }\n\n return (\n <Paper sx={section}>\n <Typography sx={heading3}>{t('dictionary.measures')}</Typography>\n\n {fields.length > 0 ? (\n fields.map((field, index) => (\n <Fragment key={field.id}>\n <Divider />\n <ActionBox\n action={currentActions[index]}\n index={index}\n formMethods={formMethods}\n remove={remove}\n onSubmit={onSubmit}\n />\n </Fragment>\n ))\n ) : (\n <Typography sx={emptyState}>\n {t('dictionary.emptyField', {\n field: t('dictionary.measures').toLowerCase(),\n })}\n </Typography>\n )}\n </Paper>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAuBO,SAAS,cAAe,CAAA;AAAA,EAC7B,WAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAuB,EAAA;AACrB,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,wBAAwB,CAAA;AAExD,EAAM,MAAA,EAAE,OAAS,EAAA,KAAA,EAAU,GAAA,WAAA;AAC3B,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAQ,EAAA,MAAA,KAAW,aAAc,CAAA;AAAA,IAC/C,OAAA;AAAA,IACA,IAAM,EAAA;AAAA,GACP,CAAA;AAED,EAAM,MAAA,cAAA,GAAiB,MAAM,SAAS,CAAA;AAEtC,EAAA,IAAI,SAAW,EAAA;AACb,IACE,uBAAA,IAAA,CAAC,KAAM,EAAA,EAAA,EAAA,EAAI,OACT,EAAA,QAAA,EAAA;AAAA,sBAAC,IAAA,CAAA,GAAA,EAAA,EAAI,IAAI,EAAE,OAAA,EAAS,QAAQ,UAAY,EAAA,QAAA,EAAU,GAAK,EAAA,CAAA,EACrD,EAAA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,EAAA,EAAI,QAAW,EAAA,QAAA,EAAA,CAAA,CAAE,oBAAoB,CAAE,EAAA,CAAA;AAAA,wBACnD,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,sBAAY,SAAU,EAAA,EAAA,CAAA;AAAA,YACtB,KAAM,EAAA,SAAA;AAAA,YACN,OAAS,EAAA,MAAM,MAAO,CAAA,WAAA,EAAa,CAAA;AAAA,YAElC,YAAE,4CAA4C;AAAA;AAAA;AACjD,OACF,EAAA,CAAA;AAAA,MACC,OAAO,GAAI,CAAA,CAAC,KAAO,EAAA,KAAA,0BACjB,QACC,EAAA,EAAA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,OAAA,EAAA,EAAQ,SAAQ,WAAY,EAAA,CAAA;AAAA,wBAC7B,GAAA;AAAA,UAAC,cAAA;AAAA,UAAA;AAAA,YAEC,WAAA;AAAA,YACA,KAAA;AAAA,YACA;AAAA,WAAA;AAAA,UAHK;AAAA;AAIP,OAPa,EAAA,EAAA,KAAA,CAAM,EAQrB,CACD;AAAA,KACH,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,IAAA,CAAC,KAAM,EAAA,EAAA,EAAA,EAAI,OACT,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,EAAA,EAAI,QAAW,EAAA,QAAA,EAAA,CAAA,CAAE,qBAAqB,CAAE,EAAA,CAAA;AAAA,IAEnD,MAAA,CAAO,SAAS,CACf,GAAA,MAAA,CAAO,IAAI,CAAC,KAAA,EAAO,KACjB,qBAAA,IAAA,CAAC,QACC,EAAA,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,OAAQ,EAAA,EAAA,CAAA;AAAA,sBACT,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,MAAA,EAAQ,eAAe,KAAK,CAAA;AAAA,UAC5B,KAAA;AAAA,UACA,WAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA;AAAA;AACF,KARa,EAAA,EAAA,KAAA,CAAM,EASrB,CACD,CAAA,uBAEA,UAAW,EAAA,EAAA,EAAA,EAAI,UACb,EAAA,QAAA,EAAA,CAAA,CAAE,uBAAyB,EAAA;AAAA,MAC1B,KAAO,EAAA,CAAA,CAAE,qBAAqB,CAAA,CAAE,WAAY;AAAA,KAC7C,CACH,EAAA;AAAA,GAEJ,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ActionsSection.esm.js","sources":["../../../../src/components/scenarioDrawer/components/ActionsSection.tsx"],"sourcesContent":["import { ActionBox } from './ActionBox';\nimport { Fragment, useMemo, useState } from 'react';\nimport Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { pluginRiScTranslationRef } from '../../../utils/translations';\nimport { emptyAction, useScenario } from '../../../contexts/ScenarioContext';\nimport { section } from '../scenarioDrawerComponents';\nimport { emptyState, heading3 } from '../../common/typography';\nimport Divider from '@mui/material/Divider';\nimport { useFieldArray, UseFormReturn } from 'react-hook-form';\nimport { FormScenario } from '../../../utils/types';\nimport { ActionFormItem } from './ActionFormItem';\nimport Button from '@mui/material/Button';\nimport { AddCircle } from '@mui/icons-material';\nimport Box from '@mui/material/Box';\nimport { ActionStatusOptions } from '../../../utils/constants';\nimport { useDebounce } from '../../../utils/hooks';\n\ntype ActionSectionProps = {\n formMethods: UseFormReturn<FormScenario>;\n isEditing: boolean;\n onSubmit: () => void;\n};\n\nexport function ActionsSection({\n formMethods,\n isEditing,\n onSubmit,\n}: ActionSectionProps) {\n const { t } = useTranslationRef(pluginRiScTranslationRef);\n\n const { control, watch } = formMethods;\n const { fields, append, remove } = useFieldArray({\n control,\n name: 'actions',\n });\n\n const currentActions = watch('actions');\n\n const sortedActionsWithIndex = useMemo(() => {\n if (!currentActions || currentActions.length === 0) return [];\n\n return currentActions\n .map((action, originalIndex) => ({ action, originalIndex }))\n .sort((a, b) => {\n if (\n a.action.status === ActionStatusOptions.NotRelevant &&\n b.action.status !== ActionStatusOptions.NotRelevant\n ) {\n return 1;\n }\n if (\n b.action.status === ActionStatusOptions.NotRelevant &&\n a.action.status !== ActionStatusOptions.NotRelevant\n ) {\n return -1;\n }\n return 0;\n });\n }, [currentActions]);\n\n const [currentUpdatedActionIDs, setCurrentUpdatedActionIDs] = useState<\n string[]\n >([]);\n\n const { submitEditedScenarioToRiSc, scenario } = useScenario();\n\n useDebounce(currentUpdatedActionIDs, 6000, updatedIDs => {\n if (updatedIDs.length === 0) return;\n const updatedScenario = {\n ...scenario,\n actions: scenario.actions.map(a =>\n updatedIDs.find(id => id === a.ID)\n ? { ...a, lastUpdated: new Date() }\n : a,\n ),\n };\n submitEditedScenarioToRiSc(updatedScenario);\n setCurrentUpdatedActionIDs([]);\n });\n\n if (isEditing) {\n return (\n <Paper sx={section}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={heading3}>{t('dictionary.measure')}</Typography>\n <Button\n startIcon={<AddCircle />}\n color=\"primary\"\n onClick={() => append(emptyAction())}\n >\n {t('scenarioDrawer.measureTab.addMeasureButton')}\n </Button>\n </Box>\n {fields.map((field, index) => (\n <Fragment key={field.id}>\n <Divider variant=\"fullWidth\" />\n <ActionFormItem\n key={index}\n formMethods={formMethods}\n index={index}\n remove={remove}\n />\n </Fragment>\n ))}\n </Paper>\n );\n }\n\n return (\n <Paper sx={section}>\n <Typography sx={heading3}>{t('dictionary.measures')}</Typography>\n\n {sortedActionsWithIndex.length > 0 ? (\n sortedActionsWithIndex.map(({ action, originalIndex }) => (\n <Fragment key={fields[originalIndex].id}>\n <Divider />\n <ActionBox\n action={action}\n index={originalIndex}\n formMethods={formMethods}\n remove={remove}\n onSubmit={onSubmit}\n setCurrentUpdatedActionIDs={setCurrentUpdatedActionIDs}\n />\n </Fragment>\n ))\n ) : (\n <Typography sx={emptyState}>\n {t('dictionary.emptyField', {\n field: t('dictionary.measures').toLowerCase(),\n })}\n </Typography>\n )}\n </Paper>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -266,6 +266,22 @@ function useIsMounted() {
266
266
  }, []);
267
267
  return useCallback(() => mountedRef.current, []);
268
268
  }
269
+ function useDebounce(value, delay, callback) {
270
+ const timeoutRef = useRef(null);
271
+ useEffect(() => {
272
+ if (timeoutRef.current) {
273
+ clearTimeout(timeoutRef.current);
274
+ }
275
+ timeoutRef.current = setTimeout(() => {
276
+ callback(value);
277
+ }, delay);
278
+ return () => {
279
+ if (timeoutRef.current) {
280
+ clearTimeout(timeoutRef.current);
281
+ }
282
+ };
283
+ }, [value, delay, callback]);
284
+ }
269
285
 
270
- export { useAuthenticatedFetch, useGithubRepositoryInformation, useIsMounted };
286
+ export { useAuthenticatedFetch, useDebounce, useGithubRepositoryInformation, useIsMounted };
271
287
  //# sourceMappingURL=hooks.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.esm.js","sources":["../../src/utils/hooks.ts"],"sourcesContent":["import {\n configApiRef,\n fetchApiRef,\n githubAuthApiRef,\n googleAuthApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { URLS } from '../urls';\nimport {\n CreateRiScResultDTO,\n GcpCryptoKeyObject,\n ProcessRiScResultDTO,\n PublishRiScResultDTO,\n RiScContentResultDTO,\n SopsConfigDTO,\n profileInfoToDTOString,\n riScToDTOString,\n DeleteRiScResultDTO,\n} from './DTOs';\nimport { latestSupportedVersion } from './constants';\nimport {\n DifferenceDTO,\n GithubRepoInfo,\n RiSc,\n RiScWithMetadata,\n SubmitResponseObject,\n} from './types';\n\nexport function useGithubRepositoryInformation(): GithubRepoInfo {\n const [, org, repo] =\n useEntity().entity.metadata.annotations?.['backstage.io/view-url'].match(\n /github\\.com\\/([^\\/]+)\\/([^\\/]+)/,\n ) || [];\n\n return {\n owner: org,\n name: repo,\n };\n}\n\nexport function useAuthenticatedFetch() {\n const repoInformation = useGithubRepositoryInformation();\n const googleApi = useApi(googleAuthApiRef);\n const gitHubApi = useApi(githubAuthApiRef);\n const identityApi = useApi(identityApiRef);\n const { fetch } = useApi(fetchApiRef);\n const backendUrl = useApi(configApiRef).getString('backend.baseUrl');\n const riScUri = `${backendUrl}${URLS.backend.riScUri_temp}/${repoInformation.owner}/${repoInformation.name}`; // URLS.backend.riScUri\n\n const uriToFetchAllRiScs = `${riScUri}/${latestSupportedVersion}/all`; // URLS.backend.fetchAllRiScs\n\n function uriToFetchDifference(id: string) {\n // URLS.backend.fetchDifference\n return `${riScUri}/${id}/difference`;\n }\n\n function uriToFetchRiSc(id: string) {\n // URLS.backend.fetchRiSc\n return `${riScUri}/${id}`;\n }\n\n function uriToDeleteRiSc(id: string) {\n // URLS.backend.deleteRiSc\n return `${riScUri}/${id}`;\n }\n\n function uriToPublishRiSc(id: string) {\n // URLS.backend.publishRiSc\n return `${riScUri}/publish/${id}`;\n }\n\n function useResponse(): [\n SubmitResponseObject | null,\n (submitStatus: SubmitResponseObject | null) => void,\n ] {\n const [submitResponse, setSubmitResponse] =\n useState<SubmitResponseObject | null>(null);\n // use callback to avoid infinite loop\n const displaySubmitResponse = useCallback(\n (submitStatus: SubmitResponseObject | null) => {\n setSubmitResponse(submitStatus);\n setTimeout(() => {\n setSubmitResponse(null);\n }, 10000);\n },\n [],\n );\n\n return [submitResponse, displaySubmitResponse];\n }\n\n const [response, setResponse] = useResponse();\n\n const configApi = useApi(configApiRef);\n\n function isDevelopment() {\n return configApi.getString('auth.environment') === 'development';\n }\n\n function fullyAuthenticatedFetch<T, K>(\n uri: string,\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n onSuccess: (response: T) => void,\n onError: (error: K, rejectedLogin: boolean) => void,\n body?: string,\n ) {\n Promise.all([\n identityApi.getCredentials(),\n googleApi.getAccessToken([\n URLS.external.www_googleapis_com__cloudkms,\n URLS.external.www_googleapis_com__cloud_platform,\n URLS.external.www_googleapis_com__cloudplatformprojects_readonly,\n ]),\n gitHubApi.getAccessToken(['repo']),\n ])\n .then(([idToken, googleAccessToken, gitHubAccessToken]) => {\n fetch(uri, {\n method: method,\n headers: {\n Authorization: `Bearer ${idToken.token}`,\n 'GCP-Access-Token': googleAccessToken,\n 'GitHub-Access-Token': gitHubAccessToken,\n 'Content-Type': 'application/json',\n },\n body: body,\n }).then(res => {\n if (!res.ok) {\n return res\n .json()\n .then(json => json as K)\n .then(typedJson => onError(typedJson, false))\n .catch(error => onError(error, false));\n }\n return res\n .json()\n .then(json => json as T)\n .then(typedJson => onSuccess(typedJson));\n });\n })\n .catch(error => {\n if (error.name === 'RejectedError') {\n onError(error, true);\n } else {\n onError(error, false);\n }\n });\n }\n\n function googleAuthenticatedFetch<T, K>(\n uri: string,\n method: 'GET',\n onSuccess: (response: T) => void,\n onError: (error: K, rejectedLogin: boolean) => void,\n body?: string,\n ) {\n Promise.all([\n identityApi.getCredentials(),\n googleApi.getAccessToken([\n URLS.external.www_googleapis_com__cloudkms,\n URLS.external.www_googleapis_com__cloud_platform,\n URLS.external.www_googleapis_com__cloudplatformprojects_readonly,\n ]),\n ])\n .then(([idToken, googleAccessToken]) => {\n fetch(uri, {\n method: method,\n headers: {\n Authorization: `Bearer ${idToken.token}`,\n 'GCP-Access-Token': googleAccessToken,\n 'Content-Type': 'application/json',\n },\n body: body,\n }).then(res => {\n if (!res.ok) {\n return res\n .json()\n .then(json => json as K)\n .then(typedJson => onError(typedJson, false))\n .catch(error => onError(error, false));\n }\n return res\n .json()\n .then(json => json as T)\n .then(typedJson => onSuccess(typedJson));\n });\n })\n .catch(error => {\n if (error.name === 'RejectedError') {\n onError(error, true);\n } else {\n onError(error, false);\n }\n });\n }\n\n function fetchDifference(\n selectedRiSc: RiScWithMetadata,\n onSuccess: (response: DifferenceDTO) => void,\n onError?: (loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile => {\n fullyAuthenticatedFetch<DifferenceDTO, DifferenceDTO>(\n uriToFetchDifference(selectedRiSc.id),\n 'POST',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n riScToDTOString(\n selectedRiSc.content,\n false,\n profile,\n selectedRiSc.sopsConfig,\n ),\n );\n });\n }\n\n function fetchRiScs(\n onSuccess: (response: RiScContentResultDTO[]) => void,\n onError?: (loginRejected: boolean) => void,\n ) {\n if (isDevelopment()) {\n fullyAuthenticatedFetch<RiScContentResultDTO[], RiScContentResultDTO[]>(\n uriToFetchAllRiScs,\n 'GET',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n );\n } else {\n googleAuthenticatedFetch<RiScContentResultDTO[], RiScContentResultDTO[]>(\n uriToFetchAllRiScs,\n 'GET',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n );\n }\n }\n\n function postFeedback(feedback: string): Promise<void> {\n return new Promise((resolve, reject) => {\n fullyAuthenticatedFetch<void, any>(\n `${riScUri}/feedback`,\n 'POST',\n () => resolve(),\n error => reject(error),\n feedback,\n );\n });\n }\n\n function fetchGcpCryptoKeys(\n onSuccess: (response: GcpCryptoKeyObject[]) => void,\n onError?: (error: GcpCryptoKeyObject[], loginRejected: boolean) => void,\n ) {\n googleAuthenticatedFetch<GcpCryptoKeyObject[], GcpCryptoKeyObject[]>(\n `${backendUrl}/api/proxy/risc-proxy/api/google/gcpCryptoKeys`, // URL\n 'GET',\n res => onSuccess(res),\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n );\n }\n\n function publishRiScs(\n riScId: string,\n onSuccess?: (response: PublishRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<PublishRiScResultDTO, ProcessRiScResultDTO>(\n uriToPublishRiSc(riScId),\n 'POST',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n profileInfoToDTOString(profile),\n ),\n );\n }\n\n function postRiScs(\n riSc: RiSc,\n generateDefault: boolean,\n sopsConfig: SopsConfigDTO,\n onSuccess?: (response: CreateRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<CreateRiScResultDTO, ProcessRiScResultDTO>(\n `${riScUri}?generateDefault=${generateDefault}`,\n 'POST',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n riScToDTOString(riSc, true, profile, sopsConfig),\n ),\n );\n }\n\n function putRiScs(\n riSc: RiScWithMetadata,\n onSuccess?: (response: ProcessRiScResultDTO | PublishRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<\n ProcessRiScResultDTO | PublishRiScResultDTO,\n ProcessRiScResultDTO\n >(\n uriToFetchRiSc(riSc.id),\n 'PUT',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n riScToDTOString(\n riSc.content,\n riSc.isRequiresNewApproval!!,\n profile,\n riSc.sopsConfig,\n ),\n ),\n );\n }\n\n function deleteRiScs(\n riScId: string,\n onSuccess?: (response: DeleteRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n fullyAuthenticatedFetch<DeleteRiScResultDTO, ProcessRiScResultDTO>(\n uriToDeleteRiSc(riScId),\n 'DELETE',\n res => {\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n );\n }\n\n return {\n fetchRiScs,\n fetchGcpCryptoKeys,\n postRiScs,\n putRiScs,\n deleteRiScs,\n publishRiScs,\n response,\n setResponse,\n fetchDifference,\n postFeedback,\n };\n}\n\nexport function useIsMounted() {\n const mountedRef = useRef(false);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n return useCallback(() => mountedRef.current, []);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.esm.js","sources":["../../src/utils/hooks.ts"],"sourcesContent":["import {\n configApiRef,\n fetchApiRef,\n githubAuthApiRef,\n googleAuthApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { URLS } from '../urls';\nimport {\n CreateRiScResultDTO,\n GcpCryptoKeyObject,\n ProcessRiScResultDTO,\n PublishRiScResultDTO,\n RiScContentResultDTO,\n SopsConfigDTO,\n profileInfoToDTOString,\n riScToDTOString,\n DeleteRiScResultDTO,\n} from './DTOs';\nimport { latestSupportedVersion } from './constants';\nimport {\n DifferenceDTO,\n GithubRepoInfo,\n RiSc,\n RiScWithMetadata,\n SubmitResponseObject,\n} from './types';\n\nexport function useGithubRepositoryInformation(): GithubRepoInfo {\n const [, org, repo] =\n useEntity().entity.metadata.annotations?.['backstage.io/view-url'].match(\n /github\\.com\\/([^\\/]+)\\/([^\\/]+)/,\n ) || [];\n\n return {\n owner: org,\n name: repo,\n };\n}\n\nexport function useAuthenticatedFetch() {\n const repoInformation = useGithubRepositoryInformation();\n const googleApi = useApi(googleAuthApiRef);\n const gitHubApi = useApi(githubAuthApiRef);\n const identityApi = useApi(identityApiRef);\n const { fetch } = useApi(fetchApiRef);\n const backendUrl = useApi(configApiRef).getString('backend.baseUrl');\n const riScUri = `${backendUrl}${URLS.backend.riScUri_temp}/${repoInformation.owner}/${repoInformation.name}`; // URLS.backend.riScUri\n\n const uriToFetchAllRiScs = `${riScUri}/${latestSupportedVersion}/all`; // URLS.backend.fetchAllRiScs\n\n function uriToFetchDifference(id: string) {\n // URLS.backend.fetchDifference\n return `${riScUri}/${id}/difference`;\n }\n\n function uriToFetchRiSc(id: string) {\n // URLS.backend.fetchRiSc\n return `${riScUri}/${id}`;\n }\n\n function uriToDeleteRiSc(id: string) {\n // URLS.backend.deleteRiSc\n return `${riScUri}/${id}`;\n }\n\n function uriToPublishRiSc(id: string) {\n // URLS.backend.publishRiSc\n return `${riScUri}/publish/${id}`;\n }\n\n function useResponse(): [\n SubmitResponseObject | null,\n (submitStatus: SubmitResponseObject | null) => void,\n ] {\n const [submitResponse, setSubmitResponse] =\n useState<SubmitResponseObject | null>(null);\n // use callback to avoid infinite loop\n const displaySubmitResponse = useCallback(\n (submitStatus: SubmitResponseObject | null) => {\n setSubmitResponse(submitStatus);\n setTimeout(() => {\n setSubmitResponse(null);\n }, 10000);\n },\n [],\n );\n\n return [submitResponse, displaySubmitResponse];\n }\n\n const [response, setResponse] = useResponse();\n\n const configApi = useApi(configApiRef);\n\n function isDevelopment() {\n return configApi.getString('auth.environment') === 'development';\n }\n\n function fullyAuthenticatedFetch<T, K>(\n uri: string,\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n onSuccess: (response: T) => void,\n onError: (error: K, rejectedLogin: boolean) => void,\n body?: string,\n ) {\n Promise.all([\n identityApi.getCredentials(),\n googleApi.getAccessToken([\n URLS.external.www_googleapis_com__cloudkms,\n URLS.external.www_googleapis_com__cloud_platform,\n URLS.external.www_googleapis_com__cloudplatformprojects_readonly,\n ]),\n gitHubApi.getAccessToken(['repo']),\n ])\n .then(([idToken, googleAccessToken, gitHubAccessToken]) => {\n fetch(uri, {\n method: method,\n headers: {\n Authorization: `Bearer ${idToken.token}`,\n 'GCP-Access-Token': googleAccessToken,\n 'GitHub-Access-Token': gitHubAccessToken,\n 'Content-Type': 'application/json',\n },\n body: body,\n }).then(res => {\n if (!res.ok) {\n return res\n .json()\n .then(json => json as K)\n .then(typedJson => onError(typedJson, false))\n .catch(error => onError(error, false));\n }\n return res\n .json()\n .then(json => json as T)\n .then(typedJson => onSuccess(typedJson));\n });\n })\n .catch(error => {\n if (error.name === 'RejectedError') {\n onError(error, true);\n } else {\n onError(error, false);\n }\n });\n }\n\n function googleAuthenticatedFetch<T, K>(\n uri: string,\n method: 'GET',\n onSuccess: (response: T) => void,\n onError: (error: K, rejectedLogin: boolean) => void,\n body?: string,\n ) {\n Promise.all([\n identityApi.getCredentials(),\n googleApi.getAccessToken([\n URLS.external.www_googleapis_com__cloudkms,\n URLS.external.www_googleapis_com__cloud_platform,\n URLS.external.www_googleapis_com__cloudplatformprojects_readonly,\n ]),\n ])\n .then(([idToken, googleAccessToken]) => {\n fetch(uri, {\n method: method,\n headers: {\n Authorization: `Bearer ${idToken.token}`,\n 'GCP-Access-Token': googleAccessToken,\n 'Content-Type': 'application/json',\n },\n body: body,\n }).then(res => {\n if (!res.ok) {\n return res\n .json()\n .then(json => json as K)\n .then(typedJson => onError(typedJson, false))\n .catch(error => onError(error, false));\n }\n return res\n .json()\n .then(json => json as T)\n .then(typedJson => onSuccess(typedJson));\n });\n })\n .catch(error => {\n if (error.name === 'RejectedError') {\n onError(error, true);\n } else {\n onError(error, false);\n }\n });\n }\n\n function fetchDifference(\n selectedRiSc: RiScWithMetadata,\n onSuccess: (response: DifferenceDTO) => void,\n onError?: (loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile => {\n fullyAuthenticatedFetch<DifferenceDTO, DifferenceDTO>(\n uriToFetchDifference(selectedRiSc.id),\n 'POST',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n riScToDTOString(\n selectedRiSc.content,\n false,\n profile,\n selectedRiSc.sopsConfig,\n ),\n );\n });\n }\n\n function fetchRiScs(\n onSuccess: (response: RiScContentResultDTO[]) => void,\n onError?: (loginRejected: boolean) => void,\n ) {\n if (isDevelopment()) {\n fullyAuthenticatedFetch<RiScContentResultDTO[], RiScContentResultDTO[]>(\n uriToFetchAllRiScs,\n 'GET',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n );\n } else {\n googleAuthenticatedFetch<RiScContentResultDTO[], RiScContentResultDTO[]>(\n uriToFetchAllRiScs,\n 'GET',\n onSuccess,\n (_, rejectedLogin) => {\n if (onError) onError(rejectedLogin);\n },\n );\n }\n }\n\n function postFeedback(feedback: string): Promise<void> {\n return new Promise((resolve, reject) => {\n fullyAuthenticatedFetch<void, any>(\n `${riScUri}/feedback`,\n 'POST',\n () => resolve(),\n error => reject(error),\n feedback,\n );\n });\n }\n\n function fetchGcpCryptoKeys(\n onSuccess: (response: GcpCryptoKeyObject[]) => void,\n onError?: (error: GcpCryptoKeyObject[], loginRejected: boolean) => void,\n ) {\n googleAuthenticatedFetch<GcpCryptoKeyObject[], GcpCryptoKeyObject[]>(\n `${backendUrl}/api/proxy/risc-proxy/api/google/gcpCryptoKeys`, // URL\n 'GET',\n res => onSuccess(res),\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n );\n }\n\n function publishRiScs(\n riScId: string,\n onSuccess?: (response: PublishRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<PublishRiScResultDTO, ProcessRiScResultDTO>(\n uriToPublishRiSc(riScId),\n 'POST',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n profileInfoToDTOString(profile),\n ),\n );\n }\n\n function postRiScs(\n riSc: RiSc,\n generateDefault: boolean,\n sopsConfig: SopsConfigDTO,\n onSuccess?: (response: CreateRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n return identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<CreateRiScResultDTO, ProcessRiScResultDTO>(\n `${riScUri}?generateDefault=${generateDefault}`,\n 'POST',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n riScToDTOString(riSc, true, profile, sopsConfig),\n ),\n );\n }\n\n function putRiScs(\n riSc: RiScWithMetadata,\n onSuccess?: (response: ProcessRiScResultDTO | PublishRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n identityApi.getProfileInfo().then(profile =>\n fullyAuthenticatedFetch<\n ProcessRiScResultDTO | PublishRiScResultDTO,\n ProcessRiScResultDTO\n >(\n uriToFetchRiSc(riSc.id),\n 'PUT',\n res => {\n setResponse(res);\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n riScToDTOString(\n riSc.content,\n riSc.isRequiresNewApproval!!,\n profile,\n riSc.sopsConfig,\n ),\n ),\n );\n }\n\n function deleteRiScs(\n riScId: string,\n onSuccess?: (response: DeleteRiScResultDTO) => void,\n onError?: (error: ProcessRiScResultDTO, loginRejected: boolean) => void,\n ) {\n fullyAuthenticatedFetch<DeleteRiScResultDTO, ProcessRiScResultDTO>(\n uriToDeleteRiSc(riScId),\n 'DELETE',\n res => {\n if (onSuccess) onSuccess(res);\n },\n (error, rejectedLogin) => {\n if (onError) onError(error, rejectedLogin);\n },\n );\n }\n\n return {\n fetchRiScs,\n fetchGcpCryptoKeys,\n postRiScs,\n putRiScs,\n deleteRiScs,\n publishRiScs,\n response,\n setResponse,\n fetchDifference,\n postFeedback,\n };\n}\n\nexport function useIsMounted() {\n const mountedRef = useRef(false);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n return useCallback(() => mountedRef.current, []);\n}\n\nexport function useDebounce<T>(\n value: T,\n delay: number,\n callback: (value: T) => void,\n) {\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n useEffect(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n timeoutRef.current = setTimeout(() => {\n callback(value);\n }, delay);\n\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, [value, delay, callback]);\n}\n"],"names":[],"mappings":"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"}
@@ -57,28 +57,43 @@ const UpdatedStatusEnum = {
57
57
  OUTDATED: "OUTDATED",
58
58
  VERY_OUTDATED: "VERY_OUTDATED"
59
59
  };
60
- function calculateUpdatedStatus(daysSinceLastModified, numOfCommitsBehind) {
61
- if (daysSinceLastModified === null || numOfCommitsBehind === null) {
62
- return UpdatedStatusEnum.VERY_OUTDATED;
63
- }
60
+ function calculateUpdatedStatusFromDaysOnly(daysSinceLastModified) {
61
+ if (daysSinceLastModified < 2 * 7) return UpdatedStatusEnum.UPDATED;
62
+ if (daysSinceLastModified < 4 * 7) return UpdatedStatusEnum.LITTLE_OUTDATED;
63
+ if (daysSinceLastModified < 8 * 7) return UpdatedStatusEnum.OUTDATED;
64
+ return UpdatedStatusEnum.VERY_OUTDATED;
65
+ }
66
+ function calculateUpdatedStatusFromDaysAndCommits(daysSinceLastModified, numOfCommitsBehind) {
64
67
  const days = daysSinceLastModified;
65
68
  const commits = numOfCommitsBehind;
66
69
  if (commits > 50) {
67
70
  return UpdatedStatusEnum.VERY_OUTDATED;
68
71
  }
69
- if (commits >= 26 && commits <= 50) {
72
+ if (commits > 25) {
70
73
  if (days <= 30) return UpdatedStatusEnum.LITTLE_OUTDATED;
71
- if (days >= 31 && days <= 90) return UpdatedStatusEnum.OUTDATED;
74
+ if (days <= 90) return UpdatedStatusEnum.OUTDATED;
72
75
  return UpdatedStatusEnum.VERY_OUTDATED;
73
76
  }
74
- if (commits >= 11 && commits <= 25) {
77
+ if (commits > 10) {
75
78
  if (days <= 30) return UpdatedStatusEnum.UPDATED;
76
- if (days >= 31 && days <= 90) return UpdatedStatusEnum.LITTLE_OUTDATED;
77
- if (days >= 91 && days <= 180) return UpdatedStatusEnum.OUTDATED;
79
+ if (days <= 90) return UpdatedStatusEnum.LITTLE_OUTDATED;
80
+ if (days <= 180) return UpdatedStatusEnum.OUTDATED;
78
81
  return UpdatedStatusEnum.VERY_OUTDATED;
79
82
  }
80
- if (commits <= 10) {
81
- return days <= 60 ? UpdatedStatusEnum.UPDATED : UpdatedStatusEnum.LITTLE_OUTDATED;
83
+ if (days <= 60) return UpdatedStatusEnum.UPDATED;
84
+ if (days <= 180) return UpdatedStatusEnum.LITTLE_OUTDATED;
85
+ if (days <= 360) return UpdatedStatusEnum.OUTDATED;
86
+ return UpdatedStatusEnum.VERY_OUTDATED;
87
+ }
88
+ function calculateUpdatedStatus(daysSinceLastModified, numOfCommitsBehind) {
89
+ if (daysSinceLastModified !== null && numOfCommitsBehind === null) {
90
+ return calculateUpdatedStatusFromDaysOnly(daysSinceLastModified);
91
+ }
92
+ if (daysSinceLastModified !== null && numOfCommitsBehind !== null) {
93
+ return calculateUpdatedStatusFromDaysAndCommits(
94
+ daysSinceLastModified,
95
+ numOfCommitsBehind
96
+ );
82
97
  }
83
98
  return UpdatedStatusEnum.VERY_OUTDATED;
84
99
  }
@@ -236,6 +251,26 @@ const vulnerabiltiesOptionsToTranslationKeys = {
236
251
  [VulnerabilitiesOptions.InformationLeak]: "vulnerabilities.Information leak",
237
252
  [VulnerabilitiesOptions.ExcessiveUse]: "vulnerabilities.Excessive use"
238
253
  };
254
+ const getActionStatusColor = (status) => {
255
+ switch (status) {
256
+ case ActionStatusOptions.OK:
257
+ return "success";
258
+ case ActionStatusOptions.NotOK:
259
+ return "error";
260
+ default:
261
+ return "inherit";
262
+ }
263
+ };
264
+ const getActionStatusStyle = (status) => {
265
+ const baseStyle = { color: "white" };
266
+ if (status === ActionStatusOptions.NotRelevant) {
267
+ return {
268
+ ...baseStyle,
269
+ backgroundColor: "rgba(128, 128, 128, 1)"
270
+ };
271
+ }
272
+ return baseStyle;
273
+ };
239
274
 
240
- export { UpdatedStatusEnum, actionStatusOptionsToTranslationKeys, calculateDaysSince, calculateUpdatedStatus, consequenceIndexToTranslationKeys, deleteAction, deleteScenario, emptyRiSc, findConsequenceIndex, findProbabilityIndex, formatDate, formatNOK, formatNumber, generateRandomId, getAlertSeverity, getConsequenceLevel, getProbabilityLevel, getRiskMatrixColor, getTranslatedActionStatus, getTranslationKey, isDeeplyEqual, isPublicAgeKeyValid, parseISODateFromEncryptedROS, probabilityIndexToTranslationKeys, requiresNewApproval, roundConsequenceToNearestConsequenceOption, roundProbabilityToNearestProbabilityOption, threatActorOptionsToTranslationKeys, vulnerabiltiesOptionsToTranslationKeys };
275
+ export { UpdatedStatusEnum, actionStatusOptionsToTranslationKeys, calculateDaysSince, calculateUpdatedStatus, consequenceIndexToTranslationKeys, deleteAction, deleteScenario, emptyRiSc, findConsequenceIndex, findProbabilityIndex, formatDate, formatNOK, formatNumber, generateRandomId, getActionStatusColor, getActionStatusStyle, getAlertSeverity, getConsequenceLevel, getProbabilityLevel, getRiskMatrixColor, getTranslatedActionStatus, getTranslationKey, isDeeplyEqual, isPublicAgeKeyValid, parseISODateFromEncryptedROS, probabilityIndexToTranslationKeys, requiresNewApproval, roundConsequenceToNearestConsequenceOption, roundProbabilityToNearestProbabilityOption, threatActorOptionsToTranslationKeys, vulnerabiltiesOptionsToTranslationKeys };
241
276
  //# sourceMappingURL=utilityfunctions.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utilityfunctions.esm.js","sources":["../../src/utils/utilityfunctions.ts"],"sourcesContent":["import { DateTime } from 'luxon';\nimport { UpdateStatus } from '../contexts/RiScContext';\nimport {\n ActionStatusOptions,\n BASE_NUMBER,\n CONSEQUENCE_SCALE_OFFSET,\n PROBABILITY_SCALE_OFFSET,\n ThreatActorsOptions,\n VulnerabilitiesOptions,\n latestSupportedVersion,\n riskMatrix,\n} from './constants';\nimport { RiSc, RiScWithMetadata, Risk, Scenario } from './types';\n\nexport function generateRandomId(): string {\n return [...Array(5)]\n .map(() => {\n const randomChar = Math.random().toString(36)[2];\n return Math.random() < 0.5 ? randomChar.toUpperCase() : randomChar;\n })\n .join('');\n}\n\nconst formatter = new Intl.NumberFormat('nb-NO', {\n maximumFractionDigits: 0,\n});\n\nexport function formatNOK(amount: number): string {\n return formatter.format(amount);\n}\n\nexport function getAlertSeverity(\n updateStatus: UpdateStatus,\n): 'error' | 'info' | 'warning' {\n if (updateStatus.isSuccess) {\n return 'info';\n } else if (updateStatus.isError) {\n return 'error';\n }\n return 'warning';\n}\n\nexport function getRiskMatrixColor(risiko: Risk) {\n const sannsynlighet = findProbabilityIndex(risiko.probability);\n const konsekvens = findConsequenceIndex(risiko.consequence);\n return riskMatrix[4 - konsekvens][sannsynlighet];\n}\n\nexport function getProbabilityLevel(risiko: Risk) {\n return findProbabilityIndex(risiko.probability) + 1;\n}\n\nexport function getConsequenceLevel(risiko: Risk) {\n return findConsequenceIndex(risiko.consequence) + 1;\n}\n\nexport function emptyRiSc(): RiSc {\n return {\n schemaVersion: latestSupportedVersion,\n title: '',\n scope: '',\n valuations: [],\n scenarios: [],\n };\n}\n\nexport function formatDate(date: Date | string): string {\n return new Date(date).toLocaleDateString();\n}\n\nexport function calculateDaysSince(dateString: Date) {\n const givenDate = dateString;\n const now = new Date();\n\n const diffTime = now.getTime() - givenDate.getTime();\n const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));\n\n return diffDays;\n}\n\nexport const UpdatedStatusEnum = {\n UPDATED: 'UPDATED',\n LITTLE_OUTDATED: 'LITTLE_OUTDATED',\n OUTDATED: 'OUTDATED',\n VERY_OUTDATED: 'VERY_OUTDATED',\n} as const;\n\nexport type UpdatedStatusEnumType =\n (typeof UpdatedStatusEnum)[keyof typeof UpdatedStatusEnum];\n\nexport function calculateUpdatedStatus(\n daysSinceLastModified: number | null,\n numOfCommitsBehind: number | null,\n): UpdatedStatusEnumType {\n if (daysSinceLastModified === null || numOfCommitsBehind === null) {\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n const days = daysSinceLastModified;\n const commits = numOfCommitsBehind;\n\n if (commits > 50) {\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (commits >= 26 && commits <= 50) {\n if (days <= 30) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (days >= 31 && days <= 90) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (commits >= 11 && commits <= 25) {\n if (days <= 30) return UpdatedStatusEnum.UPDATED;\n if (days >= 31 && days <= 90) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (days >= 91 && days <= 180) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (commits <= 10) {\n return days <= 60\n ? UpdatedStatusEnum.UPDATED\n : UpdatedStatusEnum.LITTLE_OUTDATED;\n }\n\n return UpdatedStatusEnum.VERY_OUTDATED;\n}\n\nexport function requiresNewApproval(oldRiSc: RiSc, updatedRiSc: RiSc): boolean {\n return !isDeeplyEqual(\n oldRiSc.scenarios.sort(\n (scenario1, scenario2) => Number(scenario1.ID) - Number(scenario2.ID),\n ),\n updatedRiSc.scenarios.sort(\n (scenario1, scenario2) => Number(scenario1.ID) - Number(scenario2.ID),\n ),\n );\n}\n\nexport function formatNumber(\n cost: number,\n t: (s: any, c: any) => string,\n): string {\n function getTranslationWithCorrectUnit(\n costValue: number,\n threshold: number,\n unit: string,\n ): string {\n return t(`riskMatrix.estimatedRisk.suffix.${unit}`, {\n count: Number(((costValue / threshold) * 1000).toFixed(0)),\n });\n }\n\n if (cost < 1e4) {\n return formatNOK(cost);\n }\n if (cost < 1e6) {\n return getTranslationWithCorrectUnit(cost, 1e6, 'thousand');\n }\n if (cost < 1e9) {\n return getTranslationWithCorrectUnit(cost, 1e9, 'million');\n }\n if (cost < 1e12) {\n return getTranslationWithCorrectUnit(cost, 1e12, 'billion');\n }\n return getTranslationWithCorrectUnit(cost, 1e15, 'trillion');\n}\n\nexport function parseISODateFromEncryptedROS(date?: string): string | null {\n // Early return if date is null or too short for an ISO date string, could happen from recursion\n if (!date || date.length < 10) {\n return null;\n }\n\n try {\n const parsedDate = DateTime.fromISO(date, { setZone: true });\n\n if (!parsedDate.isValid) {\n return parseISODateFromEncryptedROS(date.substring(1, date.length - 1));\n }\n\n return parsedDate.toISO({ suppressMilliseconds: true });\n } catch (e) {\n return null;\n }\n}\n\nexport function getTranslationKey(\n type: string,\n key: string,\n t: (s: any, c?: any) => string,\n): string {\n if (type === 'error') {\n return t([`errorMessages.${key}`, 'errorMessages.DefaultErrorMessage']);\n }\n return t(`infoMessages.${key}`);\n}\n\nexport function gcpProjectIdToReadableString(gcpProjectId: string) {\n const parts = gcpProjectId.split('-');\n parts.pop();\n return parts.join('-');\n}\n\nexport function isPublicAgeKeyValid(publicAgeKey: string) {\n if (publicAgeKey.length !== 62) {\n return false;\n }\n\n if (!publicAgeKey.startsWith('age1')) {\n return false;\n }\n\n const ageKeyRegex = /^age1[ac-hj-np-z02-9]{58}$/;\n return ageKeyRegex.test(publicAgeKey);\n}\n\nexport interface Duration {\n months: number;\n weeks: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n}\n\nexport function getPullRequestSecondaryText(\n fromDate: Date,\n userName: string,\n t: (s: any) => string,\n) {\n const now = new Date();\n const diffMilliseconds = now.getTime() - fromDate.getTime();\n\n const seconds = Math.floor(diffMilliseconds / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n const weeks = Math.floor(days / 7);\n const months =\n now.getUTCMonth() -\n fromDate.getUTCMonth() +\n (now.getUTCFullYear() - fromDate.getUTCFullYear()) * 12;\n\n const text = t('sopsConfigDialog.secondaryPullRequestText');\n\n // Rounding up (like GitHub?)\n if (months > 0) {\n return `${text.replace(\n '_n_',\n `${months} ${\n months > 1 ? t('dictionary.months') : t('dictionary.month')\n }`,\n )} ${userName}`;\n }\n if (weeks > 0) {\n return `${text.replace(\n '_n_',\n `${weeks} ${weeks > 1 ? t('dictionary.weeks') : t('dictionary.week')}`,\n )} ${userName}`;\n }\n if (days > 0) {\n const remainingHours = hours % 24;\n const adjustedDays = remainingHours >= 12 ? days + 1 : days;\n return `${text.replace(\n '_n_',\n `${adjustedDays} ${\n adjustedDays > 1 ? t('dictionary.days') : t('dictionary.day')\n }`,\n )} ${userName}`;\n }\n if (hours > 0) {\n const remainingMinutes = minutes % 60;\n const adjustedHours = remainingMinutes >= 30 ? hours + 1 : hours;\n return `${text.replace(\n '_n_',\n `${adjustedHours} ${\n adjustedHours > 1 ? t('dictionary.hours') : t('dictionary.hour')\n }`,\n )} ${userName}`;\n }\n if (minutes > 0) {\n const remainingSeconds = seconds % 60;\n const adjustedMinutes = remainingSeconds >= 30 ? minutes + 1 : minutes;\n return `${text.replace(\n '_n_',\n `${adjustedMinutes} ${\n adjustedMinutes > 1 ? t('dictionary.minutes') : t('dictionary.minute')\n }`,\n )} ${userName}`;\n }\n return `${text.replace(\n '_n_',\n `${seconds} ${\n seconds > 1 ? t('dictionary.seconds') : t('dictionary.second')\n }`,\n )} ${userName}`;\n}\n\nexport function deleteScenario(\n riSc: RiScWithMetadata | null,\n updateRiSc: (\n riSc: RiScWithMetadata,\n onSuccess?: () => void,\n onError?: () => void,\n ) => void,\n scenario: Scenario,\n) {\n if (riSc) {\n const updatedScenarios = riSc.content.scenarios.filter(\n s => s.ID !== scenario.ID,\n );\n updateRiSc({\n ...riSc,\n content: { ...riSc.content, scenarios: updatedScenarios },\n });\n }\n}\n\nexport function deleteAction(\n remove: (index?: number | number[]) => void,\n index: number,\n onSubmit: () => void,\n) {\n remove(index);\n onSubmit();\n}\n\n/**\n * A recursive method for determining if a and b are deeply equal. Keys in the ignoredKeys argument are ignored in the\n * comparison, i.e., they are considered non-existing in both a and b.\n */\nexport function isDeeplyEqual<T>(\n a: T,\n b: T,\n ignoredKeys: string[] = [],\n): boolean {\n // If objects are equal, there is no need compare them any further.\n if (a === b) return true;\n\n // Only do comparison on objects, ignoring null (which maps to object).\n if (a && b && typeof a === 'object' && typeof b === 'object') {\n // Check if a and b are both arrays or not. If only one is, then a and b are not equal. It is necessary to perform\n // this check, as otherwise the method below will say that [] and {} are equal (or [0] and {0: 0}).\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n // Check if a and b have the same number of entries\n if (\n Object.keys(a).filter(key => !ignoredKeys.includes(key)).length !==\n Object.keys(b).filter(key => !ignoredKeys.includes(key)).length\n )\n return false;\n\n // Check if every key of a is a key of b and that the entry associated with the key is deeply the same in a and b.\n // Since a and b has the same number of entries, it is sufficient to check only the keys of a.\n return Object.entries(a).every(\n ([key, value]) =>\n ignoredKeys.includes(key) ||\n (Object.hasOwn(b, key as keyof T) &&\n isDeeplyEqual(value, b[key as keyof T])),\n );\n }\n\n // If a or b is null or a primitive type, then they are not equal as a === b should have returned true already.\n return false;\n}\n\nfunction logBase(value: number, base: number): number {\n return Math.log(value) / Math.log(base);\n}\n\n/*\n Probability is categorized in 5 levels on a logarithmic scale with base 20:\n 0 = 20^-2 = 1 / 400\n 1 = 20^-1 = 1 / 20\n 2 = 20^-0 = 1\n 3 = 20^1 = 20\n 4 = 20^2 = 400\n*/\nexport function findProbabilityIndex(probability: number): number {\n const probabilityIndex = Math.round(\n logBase(probability, BASE_NUMBER) - PROBABILITY_SCALE_OFFSET,\n );\n return Math.min(4, Math.max(0, probabilityIndex));\n}\n\n/*\n Consequence is categorized in 5 levels on a logarithmic scale with base 20:\n 0 = 20^3 = 8 000\n 1 = 20^4 = 160 000\n 2 = 20^5 = 3 200 000\n 3 = 20^6 = 64 000 000\n 4 = 20^7 = 1 280 000 000\n*/\nexport function findConsequenceIndex(consequence: number): number {\n const consequenceIndex = Math.round(\n logBase(consequence, BASE_NUMBER) - CONSEQUENCE_SCALE_OFFSET,\n );\n return Math.min(4, Math.max(0, consequenceIndex));\n}\n\n/*\n Logarithmically round the consequence to the nearest consequence option.\n*/\nexport function roundConsequenceToNearestConsequenceOption(\n consequence: number,\n): number {\n return Math.pow(BASE_NUMBER, findConsequenceIndex(consequence) + 3);\n}\n\n/*\n Logarithmically round the probability to the nearest probability option.\n*/\nexport function roundProbabilityToNearestProbabilityOption(\n probability: number,\n): number {\n return Math.pow(BASE_NUMBER, findProbabilityIndex(probability) - 2);\n}\n\nexport const consequenceIndexToTranslationKeys: Record<number, string> = {\n 0: 'infoDialog.consequenceDescription.oneworkday',\n 1: 'infoDialog.consequenceDescription.oneworkmonth',\n 2: 'infoDialog.consequenceDescription.oneworkyear',\n 3: 'infoDialog.consequenceDescription.20workyears',\n 4: 'infoDialog.consequenceDescription.400workyears',\n};\n\nexport const probabilityIndexToTranslationKeys: Record<number, string> = {\n 0: 'infoDialog.probabilityDescription.every400years',\n 1: 'infoDialog.probabilityDescription.every20years',\n 2: 'infoDialog.probabilityDescription.annualy',\n 3: 'infoDialog.probabilityDescription.monthly',\n 4: 'infoDialog.probabilityDescription.daily',\n};\n\nexport const actionStatusOptionsToTranslationKeys: Record<\n ActionStatusOptions,\n string\n> = {\n [ActionStatusOptions.OK]: 'actionStatus.OK',\n [ActionStatusOptions.NotOK]: 'actionStatus.Not OK',\n [ActionStatusOptions.NotRelevant]: 'actionStatus.Not relevant',\n};\n\nexport function getTranslatedActionStatus(\n status: string,\n t: (key: string, options?: any) => string,\n): string {\n if (\n Object.values(ActionStatusOptions).includes(status as ActionStatusOptions)\n ) {\n return t(\n actionStatusOptionsToTranslationKeys[status as ActionStatusOptions],\n );\n }\n\n return status;\n}\n\nexport const threatActorOptionsToTranslationKeys: Record<\n ThreatActorsOptions,\n string\n> = {\n [ThreatActorsOptions.ScriptKiddie]: 'threatActors.Script kiddie',\n [ThreatActorsOptions.Hacktivist]: 'threatActors.Hacktivist',\n [ThreatActorsOptions.RecklessEmployee]: 'threatActors.Reckless employee',\n [ThreatActorsOptions.Insider]: 'threatActors.Insider',\n [ThreatActorsOptions.OrganisedCrime]: 'threatActors.Organised crime',\n [ThreatActorsOptions.TerroristOrganisation]:\n 'threatActors.Terrorist organisation',\n [ThreatActorsOptions.NationGovernment]: 'threatActors.Nation/government',\n};\n\nexport const vulnerabiltiesOptionsToTranslationKeys: Record<\n VulnerabilitiesOptions,\n string\n> = {\n [VulnerabilitiesOptions.FlawedDesign]: 'vulnerabilities.Flawed design',\n [VulnerabilitiesOptions.Misconfiguration]: 'vulnerabilities.Misconfiguration',\n [VulnerabilitiesOptions.DependencyVulnerability]:\n 'vulnerabilities.Dependency vulnerability',\n [VulnerabilitiesOptions.UnauthorizedAccess]:\n 'vulnerabilities.Unauthorized access',\n [VulnerabilitiesOptions.UnmonitoredUse]: 'vulnerabilities.Unmonitored use',\n [VulnerabilitiesOptions.InputTampering]: 'vulnerabilities.Input tampering',\n [VulnerabilitiesOptions.InformationLeak]: 'vulnerabilities.Information leak',\n [VulnerabilitiesOptions.ExcessiveUse]: 'vulnerabilities.Excessive use',\n};\n"],"names":[],"mappings":";;;AAcO,SAAS,gBAA2B,GAAA;AACzC,EAAA,OAAO,CAAC,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAChB,IAAI,MAAM;AACT,IAAA,MAAM,aAAa,IAAK,CAAA,MAAA,GAAS,QAAS,CAAA,EAAE,EAAE,CAAC,CAAA;AAC/C,IAAA,OAAO,KAAK,MAAO,EAAA,GAAI,GAAM,GAAA,UAAA,CAAW,aAAgB,GAAA,UAAA;AAAA,GACzD,CACA,CAAA,IAAA,CAAK,EAAE,CAAA;AACZ;AAEA,MAAM,SAAY,GAAA,IAAI,IAAK,CAAA,YAAA,CAAa,OAAS,EAAA;AAAA,EAC/C,qBAAuB,EAAA;AACzB,CAAC,CAAA;AAEM,SAAS,UAAU,MAAwB,EAAA;AAChD,EAAO,OAAA,SAAA,CAAU,OAAO,MAAM,CAAA;AAChC;AAEO,SAAS,iBACd,YAC8B,EAAA;AAC9B,EAAA,IAAI,aAAa,SAAW,EAAA;AAC1B,IAAO,OAAA,MAAA;AAAA,GACT,MAAA,IAAW,aAAa,OAAS,EAAA;AAC/B,IAAO,OAAA,OAAA;AAAA;AAET,EAAO,OAAA,SAAA;AACT;AAEO,SAAS,mBAAmB,MAAc,EAAA;AAC/C,EAAM,MAAA,aAAA,GAAgB,oBAAqB,CAAA,MAAA,CAAO,WAAW,CAAA;AAC7D,EAAM,MAAA,UAAA,GAAa,oBAAqB,CAAA,MAAA,CAAO,WAAW,CAAA;AAC1D,EAAA,OAAO,UAAW,CAAA,CAAA,GAAI,UAAU,CAAA,CAAE,aAAa,CAAA;AACjD;AAEO,SAAS,oBAAoB,MAAc,EAAA;AAChD,EAAO,OAAA,oBAAA,CAAqB,MAAO,CAAA,WAAW,CAAI,GAAA,CAAA;AACpD;AAEO,SAAS,oBAAoB,MAAc,EAAA;AAChD,EAAO,OAAA,oBAAA,CAAqB,MAAO,CAAA,WAAW,CAAI,GAAA,CAAA;AACpD;AAEO,SAAS,SAAkB,GAAA;AAChC,EAAO,OAAA;AAAA,IACL,aAAe,EAAA,sBAAA;AAAA,IACf,KAAO,EAAA,EAAA;AAAA,IACP,KAAO,EAAA,EAAA;AAAA,IACP,YAAY,EAAC;AAAA,IACb,WAAW;AAAC,GACd;AACF;AAEO,SAAS,WAAW,IAA6B,EAAA;AACtD,EAAA,OAAO,IAAI,IAAA,CAAK,IAAI,CAAA,CAAE,kBAAmB,EAAA;AAC3C;AAEO,SAAS,mBAAmB,UAAkB,EAAA;AACnD,EAAA,MAAM,SAAY,GAAA,UAAA;AAClB,EAAM,MAAA,GAAA,uBAAU,IAAK,EAAA;AAErB,EAAA,MAAM,QAAW,GAAA,GAAA,CAAI,OAAQ,EAAA,GAAI,UAAU,OAAQ,EAAA;AACnD,EAAA,MAAM,WAAW,IAAK,CAAA,KAAA,CAAM,YAAY,GAAO,GAAA,EAAA,GAAK,KAAK,EAAG,CAAA,CAAA;AAE5D,EAAO,OAAA,QAAA;AACT;AAEO,MAAM,iBAAoB,GAAA;AAAA,EAC/B,OAAS,EAAA,SAAA;AAAA,EACT,eAAiB,EAAA,iBAAA;AAAA,EACjB,QAAU,EAAA,UAAA;AAAA,EACV,aAAe,EAAA;AACjB;AAKgB,SAAA,sBAAA,CACd,uBACA,kBACuB,EAAA;AACvB,EAAI,IAAA,qBAAA,KAA0B,IAAQ,IAAA,kBAAA,KAAuB,IAAM,EAAA;AACjE,IAAA,OAAO,iBAAkB,CAAA,aAAA;AAAA;AAG3B,EAAA,MAAM,IAAO,GAAA,qBAAA;AACb,EAAA,MAAM,OAAU,GAAA,kBAAA;AAEhB,EAAA,IAAI,UAAU,EAAI,EAAA;AAChB,IAAA,OAAO,iBAAkB,CAAA,aAAA;AAAA;AAG3B,EAAI,IAAA,OAAA,IAAW,EAAM,IAAA,OAAA,IAAW,EAAI,EAAA;AAClC,IAAI,IAAA,IAAA,IAAQ,EAAI,EAAA,OAAO,iBAAkB,CAAA,eAAA;AACzC,IAAA,IAAI,IAAQ,IAAA,EAAA,IAAM,IAAQ,IAAA,EAAA,SAAW,iBAAkB,CAAA,QAAA;AACvD,IAAA,OAAO,iBAAkB,CAAA,aAAA;AAAA;AAG3B,EAAI,IAAA,OAAA,IAAW,EAAM,IAAA,OAAA,IAAW,EAAI,EAAA;AAClC,IAAI,IAAA,IAAA,IAAQ,EAAI,EAAA,OAAO,iBAAkB,CAAA,OAAA;AACzC,IAAA,IAAI,IAAQ,IAAA,EAAA,IAAM,IAAQ,IAAA,EAAA,SAAW,iBAAkB,CAAA,eAAA;AACvD,IAAA,IAAI,IAAQ,IAAA,EAAA,IAAM,IAAQ,IAAA,GAAA,SAAY,iBAAkB,CAAA,QAAA;AACxD,IAAA,OAAO,iBAAkB,CAAA,aAAA;AAAA;AAG3B,EAAA,IAAI,WAAW,EAAI,EAAA;AACjB,IAAA,OAAO,IAAQ,IAAA,EAAA,GACX,iBAAkB,CAAA,OAAA,GAClB,iBAAkB,CAAA,eAAA;AAAA;AAGxB,EAAA,OAAO,iBAAkB,CAAA,aAAA;AAC3B;AAEgB,SAAA,mBAAA,CAAoB,SAAe,WAA4B,EAAA;AAC7E,EAAA,OAAO,CAAC,aAAA;AAAA,IACN,QAAQ,SAAU,CAAA,IAAA;AAAA,MAChB,CAAC,WAAW,SAAc,KAAA,MAAA,CAAO,UAAU,EAAE,CAAA,GAAI,MAAO,CAAA,SAAA,CAAU,EAAE;AAAA,KACtE;AAAA,IACA,YAAY,SAAU,CAAA,IAAA;AAAA,MACpB,CAAC,WAAW,SAAc,KAAA,MAAA,CAAO,UAAU,EAAE,CAAA,GAAI,MAAO,CAAA,SAAA,CAAU,EAAE;AAAA;AACtE,GACF;AACF;AAEgB,SAAA,YAAA,CACd,MACA,CACQ,EAAA;AACR,EAAS,SAAA,6BAAA,CACP,SACA,EAAA,SAAA,EACA,IACQ,EAAA;AACR,IAAO,OAAA,CAAA,CAAE,CAAmC,gCAAA,EAAA,IAAI,CAAI,CAAA,EAAA;AAAA,MAClD,OAAO,MAAS,CAAA,CAAA,SAAA,GAAY,YAAa,GAAM,EAAA,OAAA,CAAQ,CAAC,CAAC;AAAA,KAC1D,CAAA;AAAA;AAGH,EAAA,IAAI,OAAO,GAAK,EAAA;AACd,IAAA,OAAO,UAAU,IAAI,CAAA;AAAA;AAEvB,EAAA,IAAI,OAAO,GAAK,EAAA;AACd,IAAO,OAAA,6BAAA,CAA8B,IAAM,EAAA,GAAA,EAAK,UAAU,CAAA;AAAA;AAE5D,EAAA,IAAI,OAAO,GAAK,EAAA;AACd,IAAO,OAAA,6BAAA,CAA8B,IAAM,EAAA,GAAA,EAAK,SAAS,CAAA;AAAA;AAE3D,EAAA,IAAI,OAAO,IAAM,EAAA;AACf,IAAO,OAAA,6BAAA,CAA8B,IAAM,EAAA,IAAA,EAAM,SAAS,CAAA;AAAA;AAE5D,EAAO,OAAA,6BAAA,CAA8B,IAAM,EAAA,IAAA,EAAM,UAAU,CAAA;AAC7D;AAEO,SAAS,6BAA6B,IAA8B,EAAA;AAEzE,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAK,CAAA,MAAA,GAAS,EAAI,EAAA;AAC7B,IAAO,OAAA,IAAA;AAAA;AAGT,EAAI,IAAA;AACF,IAAA,MAAM,aAAa,QAAS,CAAA,OAAA,CAAQ,MAAM,EAAE,OAAA,EAAS,MAAM,CAAA;AAE3D,IAAI,IAAA,CAAC,WAAW,OAAS,EAAA;AACvB,MAAA,OAAO,6BAA6B,IAAK,CAAA,SAAA,CAAU,GAAG,IAAK,CAAA,MAAA,GAAS,CAAC,CAAC,CAAA;AAAA;AAGxE,IAAA,OAAO,UAAW,CAAA,KAAA,CAAM,EAAE,oBAAA,EAAsB,MAAM,CAAA;AAAA,WAC/C,CAAG,EAAA;AACV,IAAO,OAAA,IAAA;AAAA;AAEX;AAEgB,SAAA,iBAAA,CACd,IACA,EAAA,GAAA,EACA,CACQ,EAAA;AACR,EAAA,IAAI,SAAS,OAAS,EAAA;AACpB,IAAA,OAAO,EAAE,CAAC,CAAA,cAAA,EAAiB,GAAG,CAAA,CAAA,EAAI,mCAAmC,CAAC,CAAA;AAAA;AAExE,EAAO,OAAA,CAAA,CAAE,CAAgB,aAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAChC;AAQO,SAAS,oBAAoB,YAAsB,EAAA;AACxD,EAAI,IAAA,YAAA,CAAa,WAAW,EAAI,EAAA;AAC9B,IAAO,OAAA,KAAA;AAAA;AAGT,EAAA,IAAI,CAAC,YAAA,CAAa,UAAW,CAAA,MAAM,CAAG,EAAA;AACpC,IAAO,OAAA,KAAA;AAAA;AAGT,EAAA,MAAM,WAAc,GAAA,4BAAA;AACpB,EAAO,OAAA,WAAA,CAAY,KAAK,YAAY,CAAA;AACtC;AAoFgB,SAAA,cAAA,CACd,IACA,EAAA,UAAA,EAKA,QACA,EAAA;AACA,EAAA,IAAI,IAAM,EAAA;AACR,IAAM,MAAA,gBAAA,GAAmB,IAAK,CAAA,OAAA,CAAQ,SAAU,CAAA,MAAA;AAAA,MAC9C,CAAA,CAAA,KAAK,CAAE,CAAA,EAAA,KAAO,QAAS,CAAA;AAAA,KACzB;AACA,IAAW,UAAA,CAAA;AAAA,MACT,GAAG,IAAA;AAAA,MACH,SAAS,EAAE,GAAG,IAAK,CAAA,OAAA,EAAS,WAAW,gBAAiB;AAAA,KACzD,CAAA;AAAA;AAEL;AAEgB,SAAA,YAAA,CACd,MACA,EAAA,KAAA,EACA,QACA,EAAA;AACA,EAAA,MAAA,CAAO,KAAK,CAAA;AACZ,EAAS,QAAA,EAAA;AACX;AAMO,SAAS,aACd,CAAA,CAAA,EACA,CACA,EAAA,WAAA,GAAwB,EACf,EAAA;AAET,EAAI,IAAA,CAAA,KAAM,GAAU,OAAA,IAAA;AAGpB,EAAA,IAAI,KAAK,CAAK,IAAA,OAAO,MAAM,QAAY,IAAA,OAAO,MAAM,QAAU,EAAA;AAG5D,IAAI,IAAA,KAAA,CAAM,QAAQ,CAAC,CAAA,KAAM,MAAM,OAAQ,CAAA,CAAC,GAAU,OAAA,KAAA;AAGlD,IACE,IAAA,MAAA,CAAO,IAAK,CAAA,CAAC,CAAE,CAAA,MAAA,CAAO,SAAO,CAAC,WAAA,CAAY,QAAS,CAAA,GAAG,CAAC,CAAA,CAAE,WACzD,MAAO,CAAA,IAAA,CAAK,CAAC,CAAA,CAAE,MAAO,CAAA,CAAA,GAAA,KAAO,CAAC,WAAY,CAAA,QAAA,CAAS,GAAG,CAAC,CAAE,CAAA,MAAA;AAEzD,MAAO,OAAA,KAAA;AAIT,IAAO,OAAA,MAAA,CAAO,OAAQ,CAAA,CAAC,CAAE,CAAA,KAAA;AAAA,MACvB,CAAC,CAAC,GAAA,EAAK,KAAK,CACV,KAAA,WAAA,CAAY,SAAS,GAAG,CAAA,IACvB,MAAO,CAAA,MAAA,CAAO,GAAG,GAAc,CAAA,IAC9B,cAAc,KAAO,EAAA,CAAA,CAAE,GAAc,CAAC;AAAA,KAC5C;AAAA;AAIF,EAAO,OAAA,KAAA;AACT;AAEA,SAAS,OAAA,CAAQ,OAAe,IAAsB,EAAA;AACpD,EAAA,OAAO,KAAK,GAAI,CAAA,KAAK,CAAI,GAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AACxC;AAUO,SAAS,qBAAqB,WAA6B,EAAA;AAChE,EAAA,MAAM,mBAAmB,IAAK,CAAA,KAAA;AAAA,IAC5B,OAAA,CAAQ,WAAa,EAAA,WAAW,CAAI,GAAA;AAAA,GACtC;AACA,EAAA,OAAO,KAAK,GAAI,CAAA,CAAA,EAAG,KAAK,GAAI,CAAA,CAAA,EAAG,gBAAgB,CAAC,CAAA;AAClD;AAUO,SAAS,qBAAqB,WAA6B,EAAA;AAChE,EAAA,MAAM,mBAAmB,IAAK,CAAA,KAAA;AAAA,IAC5B,OAAA,CAAQ,WAAa,EAAA,WAAW,CAAI,GAAA;AAAA,GACtC;AACA,EAAA,OAAO,KAAK,GAAI,CAAA,CAAA,EAAG,KAAK,GAAI,CAAA,CAAA,EAAG,gBAAgB,CAAC,CAAA;AAClD;AAKO,SAAS,2CACd,WACQ,EAAA;AACR,EAAA,OAAO,KAAK,GAAI,CAAA,WAAA,EAAa,oBAAqB,CAAA,WAAW,IAAI,CAAC,CAAA;AACpE;AAKO,SAAS,2CACd,WACQ,EAAA;AACR,EAAA,OAAO,KAAK,GAAI,CAAA,WAAA,EAAa,oBAAqB,CAAA,WAAW,IAAI,CAAC,CAAA;AACpE;AAEO,MAAM,iCAA4D,GAAA;AAAA,EACvE,CAAG,EAAA,8CAAA;AAAA,EACH,CAAG,EAAA,gDAAA;AAAA,EACH,CAAG,EAAA,+CAAA;AAAA,EACH,CAAG,EAAA,+CAAA;AAAA,EACH,CAAG,EAAA;AACL;AAEO,MAAM,iCAA4D,GAAA;AAAA,EACvE,CAAG,EAAA,iDAAA;AAAA,EACH,CAAG,EAAA,gDAAA;AAAA,EACH,CAAG,EAAA,2CAAA;AAAA,EACH,CAAG,EAAA,2CAAA;AAAA,EACH,CAAG,EAAA;AACL;AAEO,MAAM,oCAGT,GAAA;AAAA,EACF,CAAC,mBAAoB,CAAA,EAAE,GAAG,iBAAA;AAAA,EAC1B,CAAC,mBAAoB,CAAA,KAAK,GAAG,qBAAA;AAAA,EAC7B,CAAC,mBAAoB,CAAA,WAAW,GAAG;AACrC;AAEgB,SAAA,yBAAA,CACd,QACA,CACQ,EAAA;AACR,EAAA,IACE,OAAO,MAAO,CAAA,mBAAmB,CAAE,CAAA,QAAA,CAAS,MAA6B,CACzE,EAAA;AACA,IAAO,OAAA,CAAA;AAAA,MACL,qCAAqC,MAA6B;AAAA,KACpE;AAAA;AAGF,EAAO,OAAA,MAAA;AACT;AAEO,MAAM,mCAGT,GAAA;AAAA,EACF,CAAC,mBAAoB,CAAA,YAAY,GAAG,4BAAA;AAAA,EACpC,CAAC,mBAAoB,CAAA,UAAU,GAAG,yBAAA;AAAA,EAClC,CAAC,mBAAoB,CAAA,gBAAgB,GAAG,gCAAA;AAAA,EACxC,CAAC,mBAAoB,CAAA,OAAO,GAAG,sBAAA;AAAA,EAC/B,CAAC,mBAAoB,CAAA,cAAc,GAAG,8BAAA;AAAA,EACtC,CAAC,mBAAoB,CAAA,qBAAqB,GACxC,qCAAA;AAAA,EACF,CAAC,mBAAoB,CAAA,gBAAgB,GAAG;AAC1C;AAEO,MAAM,sCAGT,GAAA;AAAA,EACF,CAAC,sBAAuB,CAAA,YAAY,GAAG,+BAAA;AAAA,EACvC,CAAC,sBAAuB,CAAA,gBAAgB,GAAG,kCAAA;AAAA,EAC3C,CAAC,sBAAuB,CAAA,uBAAuB,GAC7C,0CAAA;AAAA,EACF,CAAC,sBAAuB,CAAA,kBAAkB,GACxC,qCAAA;AAAA,EACF,CAAC,sBAAuB,CAAA,cAAc,GAAG,iCAAA;AAAA,EACzC,CAAC,sBAAuB,CAAA,cAAc,GAAG,iCAAA;AAAA,EACzC,CAAC,sBAAuB,CAAA,eAAe,GAAG,kCAAA;AAAA,EAC1C,CAAC,sBAAuB,CAAA,YAAY,GAAG;AACzC;;;;"}
1
+ {"version":3,"file":"utilityfunctions.esm.js","sources":["../../src/utils/utilityfunctions.ts"],"sourcesContent":["import { DateTime } from 'luxon';\nimport { UpdateStatus } from '../contexts/RiScContext';\nimport {\n ActionStatusOptions,\n BASE_NUMBER,\n CONSEQUENCE_SCALE_OFFSET,\n PROBABILITY_SCALE_OFFSET,\n ThreatActorsOptions,\n VulnerabilitiesOptions,\n latestSupportedVersion,\n riskMatrix,\n} from './constants';\nimport { RiSc, RiScWithMetadata, Risk, Scenario } from './types';\n\nexport function generateRandomId(): string {\n return [...Array(5)]\n .map(() => {\n const randomChar = Math.random().toString(36)[2];\n return Math.random() < 0.5 ? randomChar.toUpperCase() : randomChar;\n })\n .join('');\n}\n\nconst formatter = new Intl.NumberFormat('nb-NO', {\n maximumFractionDigits: 0,\n});\n\nexport function formatNOK(amount: number): string {\n return formatter.format(amount);\n}\n\nexport function getAlertSeverity(\n updateStatus: UpdateStatus,\n): 'error' | 'info' | 'warning' {\n if (updateStatus.isSuccess) {\n return 'info';\n } else if (updateStatus.isError) {\n return 'error';\n }\n return 'warning';\n}\n\nexport function getRiskMatrixColor(risiko: Risk) {\n const sannsynlighet = findProbabilityIndex(risiko.probability);\n const konsekvens = findConsequenceIndex(risiko.consequence);\n return riskMatrix[4 - konsekvens][sannsynlighet];\n}\n\nexport function getProbabilityLevel(risiko: Risk) {\n return findProbabilityIndex(risiko.probability) + 1;\n}\n\nexport function getConsequenceLevel(risiko: Risk) {\n return findConsequenceIndex(risiko.consequence) + 1;\n}\n\nexport function emptyRiSc(): RiSc {\n return {\n schemaVersion: latestSupportedVersion,\n title: '',\n scope: '',\n valuations: [],\n scenarios: [],\n };\n}\n\nexport function formatDate(date: Date | string): string {\n return new Date(date).toLocaleDateString();\n}\n\nexport function calculateDaysSince(dateString: Date) {\n const givenDate = dateString;\n const now = new Date();\n\n const diffTime = now.getTime() - givenDate.getTime();\n const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));\n\n return diffDays;\n}\n\nexport const UpdatedStatusEnum = {\n UPDATED: 'UPDATED',\n LITTLE_OUTDATED: 'LITTLE_OUTDATED',\n OUTDATED: 'OUTDATED',\n VERY_OUTDATED: 'VERY_OUTDATED',\n} as const;\n\nexport type UpdatedStatusEnumType =\n (typeof UpdatedStatusEnum)[keyof typeof UpdatedStatusEnum];\n\nfunction calculateUpdatedStatusFromDaysOnly(daysSinceLastModified: number) {\n if (daysSinceLastModified < 2 * 7) return UpdatedStatusEnum.UPDATED;\n if (daysSinceLastModified < 4 * 7) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (daysSinceLastModified < 8 * 7) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n}\n\nfunction calculateUpdatedStatusFromDaysAndCommits(\n daysSinceLastModified: number,\n numOfCommitsBehind: number,\n) {\n const days = daysSinceLastModified;\n const commits = numOfCommitsBehind;\n\n if (commits > 50) {\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (commits > 25) {\n if (days <= 30) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (days <= 90) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (commits > 10) {\n if (days <= 30) return UpdatedStatusEnum.UPDATED;\n if (days <= 90) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (days <= 180) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n }\n\n if (days <= 60) return UpdatedStatusEnum.UPDATED;\n if (days <= 180) return UpdatedStatusEnum.LITTLE_OUTDATED;\n if (days <= 360) return UpdatedStatusEnum.OUTDATED;\n return UpdatedStatusEnum.VERY_OUTDATED;\n}\n\nexport function calculateUpdatedStatus(\n daysSinceLastModified: number | null,\n numOfCommitsBehind: number | null,\n): UpdatedStatusEnumType {\n if (daysSinceLastModified !== null && numOfCommitsBehind === null) {\n return calculateUpdatedStatusFromDaysOnly(daysSinceLastModified);\n }\n\n if (daysSinceLastModified !== null && numOfCommitsBehind !== null) {\n return calculateUpdatedStatusFromDaysAndCommits(\n daysSinceLastModified,\n numOfCommitsBehind,\n );\n }\n\n return UpdatedStatusEnum.VERY_OUTDATED;\n}\n\nexport function requiresNewApproval(oldRiSc: RiSc, updatedRiSc: RiSc): boolean {\n return !isDeeplyEqual(\n oldRiSc.scenarios.sort(\n (scenario1, scenario2) => Number(scenario1.ID) - Number(scenario2.ID),\n ),\n updatedRiSc.scenarios.sort(\n (scenario1, scenario2) => Number(scenario1.ID) - Number(scenario2.ID),\n ),\n );\n}\n\nexport function formatNumber(\n cost: number,\n t: (s: any, c: any) => string,\n): string {\n function getTranslationWithCorrectUnit(\n costValue: number,\n threshold: number,\n unit: string,\n ): string {\n return t(`riskMatrix.estimatedRisk.suffix.${unit}`, {\n count: Number(((costValue / threshold) * 1000).toFixed(0)),\n });\n }\n\n if (cost < 1e4) {\n return formatNOK(cost);\n }\n if (cost < 1e6) {\n return getTranslationWithCorrectUnit(cost, 1e6, 'thousand');\n }\n if (cost < 1e9) {\n return getTranslationWithCorrectUnit(cost, 1e9, 'million');\n }\n if (cost < 1e12) {\n return getTranslationWithCorrectUnit(cost, 1e12, 'billion');\n }\n return getTranslationWithCorrectUnit(cost, 1e15, 'trillion');\n}\n\nexport function parseISODateFromEncryptedROS(date?: string): string | null {\n // Early return if date is null or too short for an ISO date string, could happen from recursion\n if (!date || date.length < 10) {\n return null;\n }\n\n try {\n const parsedDate = DateTime.fromISO(date, { setZone: true });\n\n if (!parsedDate.isValid) {\n return parseISODateFromEncryptedROS(date.substring(1, date.length - 1));\n }\n\n return parsedDate.toISO({ suppressMilliseconds: true });\n } catch (e) {\n return null;\n }\n}\n\nexport function getTranslationKey(\n type: string,\n key: string,\n t: (s: any, c?: any) => string,\n): string {\n if (type === 'error') {\n return t([`errorMessages.${key}`, 'errorMessages.DefaultErrorMessage']);\n }\n return t(`infoMessages.${key}`);\n}\n\nexport function gcpProjectIdToReadableString(gcpProjectId: string) {\n const parts = gcpProjectId.split('-');\n parts.pop();\n return parts.join('-');\n}\n\nexport function isPublicAgeKeyValid(publicAgeKey: string) {\n if (publicAgeKey.length !== 62) {\n return false;\n }\n\n if (!publicAgeKey.startsWith('age1')) {\n return false;\n }\n\n const ageKeyRegex = /^age1[ac-hj-np-z02-9]{58}$/;\n return ageKeyRegex.test(publicAgeKey);\n}\n\nexport interface Duration {\n months: number;\n weeks: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n}\n\nexport function getPullRequestSecondaryText(\n fromDate: Date,\n userName: string,\n t: (s: any) => string,\n) {\n const now = new Date();\n const diffMilliseconds = now.getTime() - fromDate.getTime();\n\n const seconds = Math.floor(diffMilliseconds / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n const weeks = Math.floor(days / 7);\n const months =\n now.getUTCMonth() -\n fromDate.getUTCMonth() +\n (now.getUTCFullYear() - fromDate.getUTCFullYear()) * 12;\n\n const text = t('sopsConfigDialog.secondaryPullRequestText');\n\n // Rounding up (like GitHub?)\n if (months > 0) {\n return `${text.replace(\n '_n_',\n `${months} ${\n months > 1 ? t('dictionary.months') : t('dictionary.month')\n }`,\n )} ${userName}`;\n }\n if (weeks > 0) {\n return `${text.replace(\n '_n_',\n `${weeks} ${weeks > 1 ? t('dictionary.weeks') : t('dictionary.week')}`,\n )} ${userName}`;\n }\n if (days > 0) {\n const remainingHours = hours % 24;\n const adjustedDays = remainingHours >= 12 ? days + 1 : days;\n return `${text.replace(\n '_n_',\n `${adjustedDays} ${\n adjustedDays > 1 ? t('dictionary.days') : t('dictionary.day')\n }`,\n )} ${userName}`;\n }\n if (hours > 0) {\n const remainingMinutes = minutes % 60;\n const adjustedHours = remainingMinutes >= 30 ? hours + 1 : hours;\n return `${text.replace(\n '_n_',\n `${adjustedHours} ${\n adjustedHours > 1 ? t('dictionary.hours') : t('dictionary.hour')\n }`,\n )} ${userName}`;\n }\n if (minutes > 0) {\n const remainingSeconds = seconds % 60;\n const adjustedMinutes = remainingSeconds >= 30 ? minutes + 1 : minutes;\n return `${text.replace(\n '_n_',\n `${adjustedMinutes} ${\n adjustedMinutes > 1 ? t('dictionary.minutes') : t('dictionary.minute')\n }`,\n )} ${userName}`;\n }\n return `${text.replace(\n '_n_',\n `${seconds} ${\n seconds > 1 ? t('dictionary.seconds') : t('dictionary.second')\n }`,\n )} ${userName}`;\n}\n\nexport function deleteScenario(\n riSc: RiScWithMetadata | null,\n updateRiSc: (\n riSc: RiScWithMetadata,\n onSuccess?: () => void,\n onError?: () => void,\n ) => void,\n scenario: Scenario,\n) {\n if (riSc) {\n const updatedScenarios = riSc.content.scenarios.filter(\n s => s.ID !== scenario.ID,\n );\n updateRiSc({\n ...riSc,\n content: { ...riSc.content, scenarios: updatedScenarios },\n });\n }\n}\n\nexport function deleteAction(\n remove: (index?: number | number[]) => void,\n index: number,\n onSubmit: () => void,\n) {\n remove(index);\n onSubmit();\n}\n\n/**\n * A recursive method for determining if a and b are deeply equal. Keys in the ignoredKeys argument are ignored in the\n * comparison, i.e., they are considered non-existing in both a and b.\n */\nexport function isDeeplyEqual<T>(\n a: T,\n b: T,\n ignoredKeys: string[] = [],\n): boolean {\n // If objects are equal, there is no need compare them any further.\n if (a === b) return true;\n\n // Only do comparison on objects, ignoring null (which maps to object).\n if (a && b && typeof a === 'object' && typeof b === 'object') {\n // Check if a and b are both arrays or not. If only one is, then a and b are not equal. It is necessary to perform\n // this check, as otherwise the method below will say that [] and {} are equal (or [0] and {0: 0}).\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n // Check if a and b have the same number of entries\n if (\n Object.keys(a).filter(key => !ignoredKeys.includes(key)).length !==\n Object.keys(b).filter(key => !ignoredKeys.includes(key)).length\n )\n return false;\n\n // Check if every key of a is a key of b and that the entry associated with the key is deeply the same in a and b.\n // Since a and b has the same number of entries, it is sufficient to check only the keys of a.\n return Object.entries(a).every(\n ([key, value]) =>\n ignoredKeys.includes(key) ||\n (Object.hasOwn(b, key as keyof T) &&\n isDeeplyEqual(value, b[key as keyof T])),\n );\n }\n\n // If a or b is null or a primitive type, then they are not equal as a === b should have returned true already.\n return false;\n}\n\nfunction logBase(value: number, base: number): number {\n return Math.log(value) / Math.log(base);\n}\n\n/*\n Probability is categorized in 5 levels on a logarithmic scale with base 20:\n 0 = 20^-2 = 1 / 400\n 1 = 20^-1 = 1 / 20\n 2 = 20^-0 = 1\n 3 = 20^1 = 20\n 4 = 20^2 = 400\n*/\nexport function findProbabilityIndex(probability: number): number {\n const probabilityIndex = Math.round(\n logBase(probability, BASE_NUMBER) - PROBABILITY_SCALE_OFFSET,\n );\n return Math.min(4, Math.max(0, probabilityIndex));\n}\n\n/*\n Consequence is categorized in 5 levels on a logarithmic scale with base 20:\n 0 = 20^3 = 8 000\n 1 = 20^4 = 160 000\n 2 = 20^5 = 3 200 000\n 3 = 20^6 = 64 000 000\n 4 = 20^7 = 1 280 000 000\n*/\nexport function findConsequenceIndex(consequence: number): number {\n const consequenceIndex = Math.round(\n logBase(consequence, BASE_NUMBER) - CONSEQUENCE_SCALE_OFFSET,\n );\n return Math.min(4, Math.max(0, consequenceIndex));\n}\n\n/*\n Logarithmically round the consequence to the nearest consequence option.\n*/\nexport function roundConsequenceToNearestConsequenceOption(\n consequence: number,\n): number {\n return Math.pow(BASE_NUMBER, findConsequenceIndex(consequence) + 3);\n}\n\n/*\n Logarithmically round the probability to the nearest probability option.\n*/\nexport function roundProbabilityToNearestProbabilityOption(\n probability: number,\n): number {\n return Math.pow(BASE_NUMBER, findProbabilityIndex(probability) - 2);\n}\n\nexport const consequenceIndexToTranslationKeys: Record<number, string> = {\n 0: 'infoDialog.consequenceDescription.oneworkday',\n 1: 'infoDialog.consequenceDescription.oneworkmonth',\n 2: 'infoDialog.consequenceDescription.oneworkyear',\n 3: 'infoDialog.consequenceDescription.20workyears',\n 4: 'infoDialog.consequenceDescription.400workyears',\n};\n\nexport const probabilityIndexToTranslationKeys: Record<number, string> = {\n 0: 'infoDialog.probabilityDescription.every400years',\n 1: 'infoDialog.probabilityDescription.every20years',\n 2: 'infoDialog.probabilityDescription.annualy',\n 3: 'infoDialog.probabilityDescription.monthly',\n 4: 'infoDialog.probabilityDescription.daily',\n};\n\nexport const actionStatusOptionsToTranslationKeys: Record<\n ActionStatusOptions,\n string\n> = {\n [ActionStatusOptions.OK]: 'actionStatus.OK',\n [ActionStatusOptions.NotOK]: 'actionStatus.Not OK',\n [ActionStatusOptions.NotRelevant]: 'actionStatus.Not relevant',\n};\n\nexport function getTranslatedActionStatus(\n status: string,\n t: (key: string, options?: any) => string,\n): string {\n if (\n Object.values(ActionStatusOptions).includes(status as ActionStatusOptions)\n ) {\n return t(\n actionStatusOptionsToTranslationKeys[status as ActionStatusOptions],\n );\n }\n\n return status;\n}\n\nexport const threatActorOptionsToTranslationKeys: Record<\n ThreatActorsOptions,\n string\n> = {\n [ThreatActorsOptions.ScriptKiddie]: 'threatActors.Script kiddie',\n [ThreatActorsOptions.Hacktivist]: 'threatActors.Hacktivist',\n [ThreatActorsOptions.RecklessEmployee]: 'threatActors.Reckless employee',\n [ThreatActorsOptions.Insider]: 'threatActors.Insider',\n [ThreatActorsOptions.OrganisedCrime]: 'threatActors.Organised crime',\n [ThreatActorsOptions.TerroristOrganisation]:\n 'threatActors.Terrorist organisation',\n [ThreatActorsOptions.NationGovernment]: 'threatActors.Nation/government',\n};\n\nexport const vulnerabiltiesOptionsToTranslationKeys: Record<\n VulnerabilitiesOptions,\n string\n> = {\n [VulnerabilitiesOptions.FlawedDesign]: 'vulnerabilities.Flawed design',\n [VulnerabilitiesOptions.Misconfiguration]: 'vulnerabilities.Misconfiguration',\n [VulnerabilitiesOptions.DependencyVulnerability]:\n 'vulnerabilities.Dependency vulnerability',\n [VulnerabilitiesOptions.UnauthorizedAccess]:\n 'vulnerabilities.Unauthorized access',\n [VulnerabilitiesOptions.UnmonitoredUse]: 'vulnerabilities.Unmonitored use',\n [VulnerabilitiesOptions.InputTampering]: 'vulnerabilities.Input tampering',\n [VulnerabilitiesOptions.InformationLeak]: 'vulnerabilities.Information leak',\n [VulnerabilitiesOptions.ExcessiveUse]: 'vulnerabilities.Excessive use',\n};\n\nexport const getActionStatusColor = (\n status: string,\n): 'success' | 'error' | 'inherit' => {\n switch (status) {\n case ActionStatusOptions.OK:\n return 'success';\n case ActionStatusOptions.NotOK:\n return 'error';\n default:\n return 'inherit';\n }\n};\n\nexport const getActionStatusStyle = (status: string) => {\n const baseStyle = { color: 'white' };\n\n if (status === ActionStatusOptions.NotRelevant) {\n return {\n ...baseStyle,\n backgroundColor: 'rgba(128, 128, 128, 1)',\n };\n }\n return baseStyle;\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kartverket/backstage-plugin-risk-scorecard",
3
- "version": "3.3.4",
3
+ "version": "3.3.10",
4
4
  "main": "dist/index.esm.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "MIT",