diff --git a/package-lock.json b/package-lock.json
index d56b126ae..ea1790cb1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.20.6-pre-38",
+ "version": "1.20.6-pre-39",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.20.6-pre-38",
+ "version": "1.20.6-pre-39",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
diff --git a/package.json b/package.json
index 9fb2d111e..afd7e06e5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.20.6-pre-38",
+ "version": "1.20.6-pre-39",
"description": "Supporting common component library",
"type": "module",
"main": "dist/index.js",
diff --git a/src/Assets/IconV2/ic-security-fixable.svg b/src/Assets/IconV2/ic-security-fixable.svg
new file mode 100644
index 000000000..c5aa54b56
--- /dev/null
+++ b/src/Assets/IconV2/ic-security-fixable.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/Assets/IconV2/ic-security-not-fixable.svg b/src/Assets/IconV2/ic-security-not-fixable.svg
new file mode 100644
index 000000000..824c5a46f
--- /dev/null
+++ b/src/Assets/IconV2/ic-security-not-fixable.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/Assets/IconV2/ic-security-vulnerability.svg b/src/Assets/IconV2/ic-security-vulnerability.svg
new file mode 100644
index 000000000..d0f3b68e6
--- /dev/null
+++ b/src/Assets/IconV2/ic-security-vulnerability.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts
index 174617070..d02ed923a 100644
--- a/src/Common/Constants.ts
+++ b/src/Common/Constants.ts
@@ -130,6 +130,9 @@ export const URLS = {
COST_CONFIGURATIONS: `${COST_VISIBILITY_ROOT}/configurations`,
// SECURITY CENTER
SECURITY_CENTER: SECURITY_CENTER_ROOT,
+ SECURITY_CENTER_OVERVIEW: `${SECURITY_CENTER_ROOT}/overview`,
+ SECURITY_CENTER_SCANS: `${SECURITY_CENTER_ROOT}/scans`,
+ SECURITY_CENTER_POLICIES: `${SECURITY_CENTER_ROOT}/policies`,
// AUTOMATION AND ENABLEMENT
AUTOMATION_AND_ENABLEMENT: AUTOMATION_AND_ENABLEMENT_ROOT,
AUTOMATION_AND_ENABLEMENT_JOB: `${AUTOMATION_AND_ENABLEMENT_ROOT}/job`,
diff --git a/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/Overview.tsx b/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/Overview.tsx
deleted file mode 100644
index a39a994ae..000000000
--- a/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/Overview.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export const Overview = () =>
Overview
diff --git a/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/index.ts b/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/index.ts
deleted file mode 100644
index bb81fdde1..000000000
--- a/src/Pages-Devtron-2.0/InfrastructureManagement/Overview/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './Overview'
diff --git a/src/Pages-Devtron-2.0/InfrastructureManagement/index.ts b/src/Pages-Devtron-2.0/InfrastructureManagement/index.ts
index 58772772f..5ccb26ffd 100644
--- a/src/Pages-Devtron-2.0/InfrastructureManagement/index.ts
+++ b/src/Pages-Devtron-2.0/InfrastructureManagement/index.ts
@@ -1,2 +1 @@
-export * from './Overview'
export * from './Shared'
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Overview/Overview.tsx b/src/Pages-Devtron-2.0/SecurityCenter/Overview/Overview.tsx
deleted file mode 100644
index a39a994ae..000000000
--- a/src/Pages-Devtron-2.0/SecurityCenter/Overview/Overview.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export const Overview = () => Overview
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Overview/index.ts b/src/Pages-Devtron-2.0/SecurityCenter/Overview/index.ts
deleted file mode 100644
index bb81fdde1..000000000
--- a/src/Pages-Devtron-2.0/SecurityCenter/Overview/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './Overview'
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/SecurityCenterIcon.tsx b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/SecurityCenterIcon.tsx
new file mode 100644
index 000000000..9ae455cee
--- /dev/null
+++ b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/SecurityCenterIcon.tsx
@@ -0,0 +1,18 @@
+import { ComponentSizeType, URLS } from 'src'
+
+import { Button, ButtonComponentType, ButtonVariantType, Icon } from '@Shared/Components'
+
+export const SecurityCenterIcon = () => (
+ }
+ variant={ButtonVariantType.borderLess}
+ linkProps={{
+ to: URLS.SECURITY_CENTER_OVERVIEW,
+ }}
+ ariaLabel="Security Center"
+ showAriaLabelInTippy
+ />
+)
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/index.ts b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/index.ts
new file mode 100644
index 000000000..ab036d2a7
--- /dev/null
+++ b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/index.ts
@@ -0,0 +1 @@
+export { getSecurityCenterBreadcrumb } from './utils'
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/utils.tsx b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/utils.tsx
new file mode 100644
index 000000000..0d7034c11
--- /dev/null
+++ b/src/Pages-Devtron-2.0/SecurityCenter/Shared/SecurityCenterIcon/utils.tsx
@@ -0,0 +1,8 @@
+import { SecurityCenterIcon } from './SecurityCenterIcon'
+
+export const getSecurityCenterBreadcrumb = () => ({
+ 'security-center': {
+ component: ,
+ linked: true,
+ },
+})
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/Shared/index.ts b/src/Pages-Devtron-2.0/SecurityCenter/Shared/index.ts
new file mode 100644
index 000000000..8e0834085
--- /dev/null
+++ b/src/Pages-Devtron-2.0/SecurityCenter/Shared/index.ts
@@ -0,0 +1 @@
+export * from './SecurityCenterIcon'
diff --git a/src/Pages-Devtron-2.0/SecurityCenter/index.ts b/src/Pages-Devtron-2.0/SecurityCenter/index.ts
index bb81fdde1..5ccb26ffd 100644
--- a/src/Pages-Devtron-2.0/SecurityCenter/index.ts
+++ b/src/Pages-Devtron-2.0/SecurityCenter/index.ts
@@ -1 +1 @@
-export * from './Overview'
+export * from './Shared'
diff --git a/src/Pages-Devtron-2.0/index.ts b/src/Pages-Devtron-2.0/index.ts
index 13e39b15c..12ea29ca5 100644
--- a/src/Pages-Devtron-2.0/index.ts
+++ b/src/Pages-Devtron-2.0/index.ts
@@ -2,3 +2,4 @@ export * from './ApplicationManagement'
export * from './CostVisibility'
export * from './DataProtectionManagement'
export * from './InfrastructureManagement'
+export * from './SecurityCenter'
diff --git a/src/Shared/Components/Charts/Chart.component.tsx b/src/Shared/Components/Charts/Chart.component.tsx
index a3d2aefd8..b874adcc5 100644
--- a/src/Shared/Components/Charts/Chart.component.tsx
+++ b/src/Shared/Components/Charts/Chart.component.tsx
@@ -22,7 +22,7 @@ import { noop, useDebounce } from '@Common/Helper'
import { DEVTRON_BASE_MAIN_ID } from '@Shared/constants'
import { useTheme } from '@Shared/Providers'
-import { drawReferenceLine, htmlLegendPlugin } from './plugins'
+import { drawCenterText, drawReferenceLine, htmlLegendPlugin } from './plugins'
import { ChartProps, GetDefaultOptionsParams, TypeAndDatasetsType } from './types'
import {
buildChartTooltipFromContext,
@@ -89,7 +89,7 @@ ChartJSTooltip.positioners.barElementCenterPositioner = (items, eventPosition) =
/**
* A versatile Chart component that renders different types of charts using Chart.js.
- * Supports area charts, pie charts, stacked bar charts (vertical/horizontal), and line charts.
+ * Supports area charts, pie charts, semi-pie charts, stacked bar charts (vertical/horizontal), and line charts.
*
* The component automatically adapts to theme changes and provides consistent styling
* across all chart types. Colors are provided by the user through the CHART_COLORS constant
@@ -117,7 +117,24 @@ ChartJSTooltip.positioners.barElementCenterPositioner = (items, eventPosition) =
* datasets={{
* datasetName: 'Adoption Rate (%)',
* yAxisValues: [45.2, 28.7, 35.4],
- * backgroundColor: ['SkyBlue300', 'AquaTeal400', 'LavenderPurple300']
+ * colors: ['SkyBlue300', 'AquaTeal400', 'LavenderPurple300']
+ * }}
+ * />
+ *
+ * [Semi-Pie Chart Example with Center Text]
+ *
*
@@ -154,9 +171,9 @@ ChartJSTooltip.positioners.barElementCenterPositioner = (items, eventPosition) =
* ```
*
* @param id - Unique identifier for the chart canvas element
- * @param type - Chart type: 'area', 'pie', 'stackedBar', 'stackedBarHorizontal', or 'line'
- * @param xAxisLabels - Array of labels for the x-axis (or categories for pie charts)
- * @param datasets - Chart data: array of datasets for most charts, single dataset object for pie charts
+ * @param type - Chart type: 'area', 'pie', 'semiPie', 'stackedBar', 'stackedBarHorizontal', or 'line'
+ * @param xAxisLabels - Array of labels for the x-axis (or categories for pie/semi-pie charts)
+ * @param datasets - Chart data: array of datasets for most charts, single dataset object for pie/semi-pie charts
*
* @performance
* **Memoization Recommendations:**
@@ -182,7 +199,9 @@ ChartJSTooltip.positioners.barElementCenterPositioner = (items, eventPosition) =
* @notes
* - Chart automatically re-renders when theme changes (light/dark mode)
* - Line charts are rendered as non-stacked and non-filled by default
- * - Pie charts expect a single dataset object instead of an array
+ * - Pie and semi-pie charts expect a single dataset object instead of an array
+ * - Semi-pie charts render as half-circles, ideal for gauges or progress indicators
+ * - Center text can be added to pie and semi-pie charts using the centerText prop
* - Colors should reference CHART_COLORS tokens for consistency
* - Component destroys and recreates Chart.js instance on prop changes for optimal performance
*/
@@ -200,6 +219,7 @@ const Chart = (props: ChartProps) => {
xScaleTitle,
yAxisMax,
yScaleTitle,
+ centerText,
} = props
const { getTooltipContent, placement } = tooltipConfig || { placement: 'top' }
@@ -277,6 +297,7 @@ const Chart = (props: ChartProps) => {
},
plugins: [
...(referenceLines ?? []).map((rl, idx) => drawReferenceLine(rl, `reference-line-${idx}`, appTheme)),
+ ...(centerText && (type === 'pie' || type === 'semiPie') ? [drawCenterText(centerText, appTheme)] : []),
...(!hideAxis ? [htmlLegendPlugin(id, legendRef, type)] : []),
],
})
@@ -284,7 +305,19 @@ const Chart = (props: ChartProps) => {
return () => {
chartRef.current.destroy()
}
- }, [type, datasets, labels, appTheme, hideAxis, referenceLines, xAxisMax, xScaleTitle, yAxisMax, yScaleTitle])
+ }, [
+ type,
+ datasets,
+ labels,
+ appTheme,
+ hideAxis,
+ referenceLines,
+ xAxisMax,
+ xScaleTitle,
+ yAxisMax,
+ yScaleTitle,
+ centerText,
+ ])
return (
({
id,
@@ -76,3 +76,23 @@ export const htmlLegendPlugin = (id: string, ref: RefObject, typ
)
},
})
+
+export const drawCenterText = (config: CenterTextConfig, appTheme: AppThemeType): Plugin => ({
+ id: 'centerText',
+ afterDraw: (chart) => {
+ const { ctx, chartArea } = chart
+ if (!config?.text) {
+ return
+ }
+
+ const centerX = (chartArea.left + chartArea.right) / 2
+
+ ctx.save()
+ ctx.font = `${config.fontWeight || '600'} ${config.fontSize || 16}px ${config.fontFamily || "'IBM Plex Sans', 'Open Sans', 'Roboto'"}`
+ ctx.fillStyle = config.color || CHART_AXIS_LABELS_COLOR[appTheme]
+ ctx.textAlign = 'center'
+ ctx.textBaseline = 'middle'
+ ctx.fillText(config.text, centerX, chartArea.bottom - 20)
+ ctx.restore()
+ },
+})
diff --git a/src/Shared/Components/Charts/types.ts b/src/Shared/Components/Charts/types.ts
index 48afbbb97..00304ec0e 100644
--- a/src/Shared/Components/Charts/types.ts
+++ b/src/Shared/Components/Charts/types.ts
@@ -5,7 +5,7 @@ import { TooltipProps } from '@Common/Tooltip'
import { AppThemeType } from '@Shared/Providers'
import { Never } from '@Shared/types'
-export type ChartType = 'area' | 'pie' | 'stackedBar' | 'stackedBarHorizontal' | 'line'
+export type ChartType = 'area' | 'pie' | 'semiPie' | 'stackedBar' | 'stackedBarHorizontal' | 'line'
export type ColorTokensType =
| 'DeepPlum'
@@ -24,7 +24,7 @@ export type VariantsType = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 |
export type ChartColorKey = `${ColorTokensType}${VariantsType}`
-export type ChartTypeWithoutPie = Exclude
+export type ChartTypeWithoutPie = Exclude
interface BaseSimpleDataset {
datasetName: string
@@ -51,6 +51,14 @@ export interface ReferenceLineConfigType {
value: number
}
+export interface CenterTextConfig {
+ text: string
+ fontSize?: number
+ fontWeight?: string | number
+ color?: string
+ fontFamily?: string
+}
+
type XYAxisMax = {
xAxisMax?: number
yAxisMax?: number
@@ -69,18 +77,21 @@ type ScaleTickFormatCallbacks = Partial<{
export type TypeAndDatasetsType =
| ({
- type: 'pie'
+ type: 'pie' | 'semiPie'
/**
* Needs to be memoized
*/
datasets: SimpleDatasetForPie
onChartClick?: OnChartClickHandler
+ /** Configuration for center text (only for doughnut/pie charts) */
+ centerText?: CenterTextConfig
} & Never &
Never)
| ({
type: 'line'
datasets: SimpleDatasetForLineAndArea[]
onChartClick?: never
+ centerText?: never
} & XYAxisMax &
ScaleTickFormatCallbacks)
| ({
@@ -88,12 +99,14 @@ export type TypeAndDatasetsType =
datasets: SimpleDatasetForLineAndArea
/* onChartClick is not applicable for area charts */
onChartClick?: never
+ centerText?: never
} & XYAxisMax &
ScaleTickFormatCallbacks)
| ({
- type: Exclude
+ type: Exclude
datasets: SimpleDataset[]
onChartClick?: OnChartClickHandler
+ centerText?: never
} & XYAxisMax &
ScaleTickFormatCallbacks)
@@ -127,7 +140,7 @@ export type TransformDatasetProps = {
appTheme: AppThemeType
} & (
| {
- type: 'pie'
+ type: 'pie' | 'semiPie'
dataset: SimpleDatasetForPie
}
| {
@@ -135,7 +148,7 @@ export type TransformDatasetProps = {
dataset: SimpleDatasetForLineAndArea
}
| {
- type: Exclude
+ type: Exclude
dataset: SimpleDataset
}
)
diff --git a/src/Shared/Components/Charts/utils.tsx b/src/Shared/Components/Charts/utils.tsx
index 3cb6357d4..d006fa675 100644
--- a/src/Shared/Components/Charts/utils.tsx
+++ b/src/Shared/Components/Charts/utils.tsx
@@ -29,6 +29,7 @@ import {
ColorTokensType,
GetBackgroundAndBorderColorProps,
GetDefaultOptionsParams,
+ SimpleDatasetForLineAndArea,
TransformDataForChartProps,
TransformDatasetProps,
VariantsType,
@@ -41,6 +42,7 @@ export const getChartJSType = (type: ChartType): ChartJSChartType => {
case 'line':
return 'line'
case 'pie':
+ case 'semiPie':
return 'doughnut'
case 'stackedBar':
case 'stackedBarHorizontal':
@@ -65,7 +67,7 @@ const handleChartClick =
const { datasetIndex, index } = elements[0]
- if (type === 'pie') {
+ if (type === 'pie' || type === 'semiPie') {
if (!datasets.isClickable?.[index]) {
return
}
@@ -94,7 +96,7 @@ const handleChartHover =
const { datasetIndex, index } = elements[0]
- if (type === 'pie') {
+ if (type === 'pie' || type === 'semiPie') {
if (!datasets.isClickable?.[index]) {
// eslint-disable-next-line no-param-reassign
canvas.style.cursor = 'default'
@@ -257,6 +259,22 @@ export const getDefaultOptions = ({
},
} satisfies ScaleOptions<'linear'>
+ const commonPieConfig = {
+ ...baseOptions,
+ plugins: {
+ ...baseOptions.plugins,
+ legend: {
+ display: false,
+ labels: {
+ textAlign: 'left',
+ },
+ position: 'right',
+ },
+ },
+ cutout: '60%',
+ radius: '100%',
+ }
+
switch (type) {
case 'area':
case 'line':
@@ -311,20 +329,12 @@ export const getDefaultOptions = ({
indexAxis: type === 'stackedBarHorizontal' ? 'y' : 'x',
} satisfies ChartOptions<'bar'>
case 'pie':
+ return commonPieConfig as ChartOptions<'doughnut'>
+ case 'semiPie':
return {
- ...baseOptions,
- plugins: {
- ...baseOptions.plugins,
- legend: {
- display: false,
- labels: {
- textAlign: 'left',
- },
- position: 'right',
- },
- },
- cutout: '60%',
- radius: '100%',
+ ...commonPieConfig,
+ rotation: -90,
+ circumference: 180,
} as ChartOptions<'doughnut'>
default:
return baseOptions
@@ -350,7 +360,7 @@ const getDarkerShadeBy = (colorKey: ChartColorKey, appTheme: AppThemeType, delta
}
const getBackgroundAndBorderColor = ({ type, dataset, appTheme }: GetBackgroundAndBorderColorProps) => {
- if (type === 'pie') {
+ if (type === 'pie' || type === 'semiPie') {
return {
backgroundColor: dataset.colors.map((colorKey) => getColorValue(colorKey, appTheme)),
hoverBackgroundColor: dataset.colors.map((colorKey) => getDarkerShadeBy(colorKey, appTheme)),
@@ -384,7 +394,9 @@ const getBackgroundAndBorderColor = ({ type, dataset, appTheme }: GetBackgroundA
>
}
- const bgColor = getColorValue(dataset.color, appTheme)
+ // At this point, we know it's an area chart (not pie/semiPie)
+ const areaDataset = dataset as SimpleDatasetForLineAndArea
+ const bgColor = getColorValue(areaDataset.color, appTheme)
return {
backgroundColor(context) {
@@ -401,7 +413,7 @@ const getBackgroundAndBorderColor = ({ type, dataset, appTheme }: GetBackgroundA
return gradient
},
- borderColor: getDarkerShadeBy(dataset.color, appTheme),
+ borderColor: getDarkerShadeBy(areaDataset.color, appTheme),
pointBackgroundColor: bgColor,
pointBorderColor: bgColor,
} as Pick, 'backgroundColor' | 'borderColor' | 'pointBackgroundColor' | 'pointBorderColor'>
@@ -463,7 +475,7 @@ export const transformDataForChart = (props: TransformDataForChartProps) => {
return []
}
- if (type !== 'pie' && type !== 'area' && !Array.isArray(datasets)) {
+ if (type !== 'pie' && type !== 'semiPie' && type !== 'area' && !Array.isArray(datasets)) {
// eslint-disable-next-line no-console
console.error('Invalid datasets format. Expected an array.')
return []
@@ -472,6 +484,7 @@ export const transformDataForChart = (props: TransformDataForChartProps) => {
switch (type) {
/** Not not clubbing it with the default case for better typing */
case 'pie':
+ case 'semiPie':
return [transformDataset({ type, dataset: datasets, appTheme })]
case 'area':
return [transformDataset({ type, dataset: datasets, appTheme })]
diff --git a/src/Shared/Components/Icon/Icon.tsx b/src/Shared/Components/Icon/Icon.tsx
index 87a6460d9..e58102abf 100644
--- a/src/Shared/Components/Icon/Icon.tsx
+++ b/src/Shared/Components/Icon/Icon.tsx
@@ -235,8 +235,11 @@ import { ReactComponent as ICResourceWatcher } from '@IconsV2/ic-resource-watche
import { ReactComponent as ICRightPanelCollapse } from '@IconsV2/ic-right-panel-collapse.svg'
import { ReactComponent as ICRocketGear } from '@IconsV2/ic-rocket-gear.svg'
import { ReactComponent as ICRocketLaunch } from '@IconsV2/ic-rocket-launch.svg'
+import { ReactComponent as ICSecurityFixable } from '@IconsV2/ic-security-fixable.svg'
+import { ReactComponent as ICSecurityNotFixable } from '@IconsV2/ic-security-not-fixable.svg'
import { ReactComponent as ICSecurityPolicy } from '@IconsV2/ic-security-policy.svg'
import { ReactComponent as ICSecurityScan } from '@IconsV2/ic-security-scan.svg'
+import { ReactComponent as ICSecurityVulnerability } from '@IconsV2/ic-security-vulnerability.svg'
import { ReactComponent as ICSelected } from '@IconsV2/ic-selected.svg'
import { ReactComponent as ICShapes } from '@IconsV2/ic-shapes.svg'
import { ReactComponent as ICShieldCheck } from '@IconsV2/ic-shield-check.svg'
@@ -537,8 +540,11 @@ export const iconMap = {
'ic-right-panel-collapse': ICRightPanelCollapse,
'ic-rocket-gear': ICRocketGear,
'ic-rocket-launch': ICRocketLaunch,
+ 'ic-security-fixable': ICSecurityFixable,
+ 'ic-security-not-fixable': ICSecurityNotFixable,
'ic-security-policy': ICSecurityPolicy,
'ic-security-scan': ICSecurityScan,
+ 'ic-security-vulnerability': ICSecurityVulnerability,
'ic-selected': ICSelected,
'ic-shapes': ICShapes,
'ic-shield-check': ICShieldCheck,
diff --git a/src/Shared/Components/Security/constants.tsx b/src/Shared/Components/Security/constants.tsx
index 65fc41c55..4e7b26ca3 100644
--- a/src/Shared/Components/Security/constants.tsx
+++ b/src/Shared/Components/Security/constants.tsx
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import { Severity } from '@Shared/types'
+
import { CATEGORIES, SUB_CATEGORIES } from './SecurityModal/types'
import { CATEGORY_LABELS } from './SecurityModal'
import { SecurityConfigType } from './types'
@@ -37,3 +39,11 @@ export const SECURITY_CONFIG: SecurityConfigType = {
subCategories: [SUB_CATEGORIES.MISCONFIGURATIONS, SUB_CATEGORIES.EXPOSED_SECRETS],
},
}
+
+export const SEVERITY_LABEL_MAP: Record = {
+ [Severity.CRITICAL]: 'Critical',
+ [Severity.HIGH]: 'High',
+ [Severity.MEDIUM]: 'Medium',
+ [Severity.LOW]: 'Low',
+ [Severity.UNKNOWN]: 'Unknown',
+}
diff --git a/src/Shared/Components/Security/index.tsx b/src/Shared/Components/Security/index.tsx
index d6b7f36b4..e7af72994 100644
--- a/src/Shared/Components/Security/index.tsx
+++ b/src/Shared/Components/Security/index.tsx
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+export { SEVERITY_LABEL_MAP } from './constants'
export * from './SecurityDetailsCards'
export * from './SecurityModal'
export * from './utils'
diff --git a/src/Shared/Components/SelectPicker/SelectPickerTextArea.component.tsx b/src/Shared/Components/SelectPicker/SelectPickerTextArea.component.tsx
index 20b16c232..414745b05 100644
--- a/src/Shared/Components/SelectPicker/SelectPickerTextArea.component.tsx
+++ b/src/Shared/Components/SelectPicker/SelectPickerTextArea.component.tsx
@@ -97,6 +97,14 @@ export const SelectPickerTextArea = ({
useThrottledEffect(reInitHeight, 500, [inputValue])
+ const handleCreateOption = (newValue: string) => {
+ onChange?.(
+ { label: newValue, value: newValue },
+ { action: 'create-option', option: { label: newValue, value: newValue } },
+ )
+ selectRef.current.blurInput()
+ }
+
const onInputChange = (newValue: string, { action }: InputActionMeta) => {
if (action === ReactSelectInputAction.inputChange) {
setInputValue(newValue)
@@ -108,20 +116,16 @@ export const SelectPickerTextArea = ({
})
}
} else if (action === ReactSelectInputAction.inputBlur) {
+ if (isCreatable) {
+ handleCreateOption(inputValue)
+ return
+ }
// Reverting input to previously selected value in case of blur event. (no-selection)
const selectValue = value as SingleValue>
setInputValue(selectValue?.value || '')
}
}
- const handleCreateOption = (newValue: string) => {
- onChange?.(
- { label: newValue, value: newValue },
- { action: 'create-option', option: { label: newValue, value: newValue } },
- )
- selectRef.current.blurInput()
- }
-
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'Enter' && event.shiftKey) {
// Prevent the default Enter key behavior
diff --git a/src/Shared/Components/Table/InternalTable.tsx b/src/Shared/Components/Table/InternalTable.tsx
index a868b5834..fc93f5203 100644
--- a/src/Shared/Components/Table/InternalTable.tsx
+++ b/src/Shared/Components/Table/InternalTable.tsx
@@ -19,7 +19,7 @@ import { Fragment, useEffect, useMemo, useRef } from 'react'
import { useQuery } from '@Common/API'
import { GenericEmptyState, GenericFilterEmptyState } from '@Common/EmptyState'
import ErrorScreenManager from '@Common/ErrorScreenManager'
-import { noop } from '@Common/Helper'
+import { noop, useAsync } from '@Common/Helper'
import { UseRegisterShortcutProvider } from '@Common/Hooks'
import { NO_ROWS_OR_GET_ROWS_ERROR } from './constants'
@@ -117,36 +117,32 @@ const InternalTable = <
handleClearBulkSelection()
}, [rows])
- // useAsync hook for 'rows' scenario
- const {
- isFetching: _areRowsLoading,
- data: rowsResult,
- error: rowsError,
- refetch: reloadRows,
- } = useQuery, unknown[], false>({
- queryFn: async () => {
- let totalRows = rows.length
- const filteredRows = await getFilteringPromise({
- searchSortTimeoutRef,
- callback: () => {
- const { rows: filteredAndSortedRows, totalRows: total } = searchAndSortRows(
- rows,
- filter,
- filterData,
- visibleColumns.find(({ field }) => field === sortBy)?.comparator,
- )
+ const handleFiltering = async () => {
+ let totalRows = rows.length
+ const filteredRows = await getFilteringPromise({
+ searchSortTimeoutRef,
+ callback: () => {
+ const { rows: filteredAndSortedRows, totalRows: total } = searchAndSortRows(
+ rows,
+ filter,
+ filterData,
+ visibleColumns.find(({ field }) => field === sortBy)?.comparator,
+ )
- totalRows = total
+ totalRows = total
- return filteredAndSortedRows
- },
- })
- return { filteredRows, totalRows }
- },
- // eslint-disable-next-line @tanstack/query/exhaustive-deps
- queryKey: [searchKey, sortBy, sortOrder, rows, JSON.stringify(otherFilters), visibleColumns],
- enabled: !!rows,
- })
+ return filteredAndSortedRows
+ },
+ })
+ return { filteredRows, totalRows }
+ }
+
+ // useAsync hook for 'rows' scenario
+ const [_areRowsLoading, rowsResult, rowsError, reloadRows] = useAsync(
+ handleFiltering,
+ [searchKey, sortBy, sortOrder, rows, JSON.stringify(otherFilters), visibleColumns],
+ !!rows,
+ )
// useAsync hook for 'getRows' scenario
const {