diff --git a/src/web/components/form/__tests__/select.jsx b/src/web/components/form/__tests__/select.jsx
index 396feb1a69..67a201a0eb 100644
--- a/src/web/components/form/__tests__/select.jsx
+++ b/src/web/components/form/__tests__/select.jsx
@@ -26,7 +26,7 @@ import {
clickElement,
} from 'web/components/testing';
-import Select from '../select';
+import Select, {SelectItem} from '../select';
describe('Select component tests', () => {
test('should render', () => {
@@ -229,6 +229,26 @@ describe('Select component tests', () => {
expect(getSelectItemElements().length).toEqual(1);
});
+ describe('SelectItemRaw', () => {
+ test.each([
+ {
+ label: 'Test Item',
+ deprecated: '1',
+ expectedText: 'Test Item (Deprecated)',
+ },
+ {
+ label: 'Non-deprecated Item',
+ deprecated: undefined,
+ expectedText: 'Non-deprecated Item',
+ },
+ ])(
+ 'renders $label correctly with deprecated status $deprecated',
+ ({label, deprecated, expectedText}) => {
+ const {getByText} = render(
+ ,
+ );
+ expect(getByText(expectedText)).toBeInTheDocument();
+ },
+ );
+ });
});
-
-// vim: set ts=2 sw=2 tw=80:
diff --git a/src/web/components/form/select.jsx b/src/web/components/form/select.jsx
index 714a8a67ec..6dfd749b09 100644
--- a/src/web/components/form/select.jsx
+++ b/src/web/components/form/select.jsx
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import {useCallback} from 'react';
+import {useCallback, forwardRef} from 'react';
import {Loader} from '@mantine/core';
@@ -28,6 +28,8 @@ import PropTypes, {mayRequire} from 'web/utils/proptypes';
import useTranslation from 'web/hooks/useTranslation';
+import {_} from 'gmp/locale/lang';
+
const findItem = (items, value) =>
isDefined(items) ? items.find(i => i.value === value) : undefined;
@@ -72,6 +74,24 @@ const SelectValueValidator = (props, propName, componentName) => {
const selectValue = mayRequire(SelectValueValidator);
+const renderLabel = props => {
+ const {label, deprecated} = props;
+
+ if (deprecated) {
+ return {`${label} (${_('Deprecated')})`};
+ }
+
+ return {label};
+};
+
+export const SelectItem = forwardRef((props, ref) => {
+ return (
+
+ {renderLabel(props)}
+
+ );
+});
+
const Select = ({
disabled,
dropdownPosition,
@@ -120,6 +140,7 @@ const Select = ({
value={selectedValue}
onChange={handleChange}
rightSection={rightSection}
+ itemComponent={SelectItem}
/>
);
};
diff --git a/src/web/utils/__tests__/render.jsx b/src/web/utils/__tests__/render.jsx
index 3ed1d74ab4..4d32a4edaf 100644
--- a/src/web/utils/__tests__/render.jsx
+++ b/src/web/utils/__tests__/render.jsx
@@ -39,31 +39,6 @@ describe('render_select_items test', () => {
expect(items[1]).toEqual({label: 'B Task', value: '2'});
});
- test('should mark deprecated items', () => {
- const entities = [
- {
- name: 'A Config',
- id: '1',
- },
- {
- name: 'B Config',
- deprecated: '1',
- id: '2',
- },
- {
- name: 'C Config',
- id: '3',
- },
- ];
-
- const items = renderSelectItems(entities);
-
- expect(items.length).toBe(3);
- expect(items[0]).toEqual({label: 'A Config', value: '1'});
- expect(items[1]).toEqual({label: B Config (Deprecated), value: '2'});
- expect(items[2]).toEqual({label: 'C Config', value: '3'});
- });
-
test('should add default item', () => {
const entities = [
{
@@ -103,6 +78,26 @@ describe('render_select_items test', () => {
expect(items[1]).toEqual({label: 'A Task', value: '1'});
expect(items[2]).toEqual({label: 'B Task', value: '2'});
});
+
+ test.each([
+ {name: 'Item 1', id: 1, deprecated: '1'},
+ {name: 'Item 2', id: 2},
+ {name: 123, id: 3, deprecated: '1'},
+ {name: true, id: 4},
+ {name: null, id: 5},
+ {name: undefined, id: 6},
+ ])('should return labels as strings for item with id %s', item => {
+ const default_item_value = 0;
+ const default_item_label = 'Default Item';
+
+ const result = renderSelectItems(
+ [item],
+ default_item_value,
+ default_item_label,
+ );
+
+ expect(typeof result[1].label).toBe('string');
+ });
});
describe('generateFilename tests', () => {
diff --git a/src/web/utils/render.jsx b/src/web/utils/render.jsx
index 972329f704..9d1a967e8d 100644
--- a/src/web/utils/render.jsx
+++ b/src/web/utils/render.jsx
@@ -30,14 +30,6 @@ import {typeName, getEntityType} from 'gmp/utils/entitytype';
export const UNSET_VALUE = '0';
export const UNSET_LABEL = '--';
-function selectItemLabel(item) {
- const itemText = isDefined(item.name) ? item.name : item.id;
- if (item.deprecated) {
- return {itemText + ' (' + _('Deprecated') + ')'};
- }
- return itemText;
-}
-
/**
* Render a entities list as items array
*
@@ -53,7 +45,11 @@ export const renderSelectItems = (
default_item_label = UNSET_LABEL,
) => {
const items = isDefined(list)
- ? list.map(item => ({label: selectItemLabel(item), value: item.id}))
+ ? list.map(item => ({
+ label: String(item.name),
+ value: item.id,
+ deprecated: item.deprecated,
+ }))
: undefined;
if (!isDefined(default_item_value)) {