-
-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3745 from 73nici/SelectBoxInvalidValues
BUGFIX: Select box shows invalid value
- Loading branch information
Showing
11 changed files
with
219 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 0 additions & 17 deletions
17
packages/neos-ui-editors/src/Editors/SelectBox/SelectBoxHelpers.js
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
packages/neos-ui-editors/src/Editors/SelectBox/selectBoxHelpers.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import {processSelectBoxOptions} from './selectBoxHelpers'; | ||
import {I18nRegistry} from '@neos-project/neos-ts-interfaces'; | ||
|
||
const fakeI18NRegistry: I18nRegistry = { | ||
translate: (id) => id ?? '' | ||
}; | ||
|
||
describe('processSelectBoxOptions', () => { | ||
it('transforms an associative array with labels to list of objects', () => { | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'}, | ||
'key2': {label: 'Key 2', icon: 'foo', disabled: true} | ||
}, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}, {value: 'key2', label: 'Key 2', icon: 'foo', disabled: true}]); | ||
}); | ||
|
||
it('keeps valid shape of list of objects intact', () => { | ||
const options = [{value: 'key1', label: 'Key 1'}, {value: 'key2', label: 'Key 2', icon: 'foo', disabled: true}]; | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, options, null); | ||
|
||
expect(processOptions).toEqual(options); | ||
}); | ||
|
||
it('overrules the array key with the explicit value', () => { | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'}, | ||
// @ts-expect-error we declare the typescript types to what we want, but cant influence user input | ||
'key2': {label: 'Key 2', value: 'key2-overrule'} | ||
}, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}, {value: 'key2-overrule', label: 'Key 2'}]); | ||
}); | ||
|
||
it('uses numeric string array key for list of objects', () => { | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, [ | ||
{value: 'key1', label: 'Key 1'}, | ||
{label: 'Key 2'} | ||
] as any, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}, {value: '1', label: 'Key 2'}]); | ||
}); | ||
|
||
it('omits entries that are invalid and empty', () => { | ||
let processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'}, | ||
// @ts-expect-error we declare the typescript types to what we want, but cant influence user input | ||
'key2': null | ||
}, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
|
||
processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'}, | ||
// @ts-expect-error we declare the typescript types to what we want, but cant influence user input | ||
'key2': {} | ||
}, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
|
||
processOptions = processSelectBoxOptions(fakeI18NRegistry, [ | ||
{value: 'key1', label: 'Key 1'}, | ||
{value: 'key2'} | ||
] as any, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
|
||
processOptions = processSelectBoxOptions(fakeI18NRegistry, [ | ||
{value: 'key1', label: 'Key 1'}, | ||
{} | ||
] as any, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
}); | ||
|
||
it('creates missing option for unmatched string value', () => { | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'} | ||
}, 'oldValue'); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}, {value: 'oldValue', label: 'Neos.Neos.Ui:Main:invalidValue: "oldValue"', icon: 'exclamation-triangle'}]); | ||
}); | ||
|
||
it('creates missing options for unmatched additional array value', () => { | ||
const processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'} | ||
}, ['oldValue', 'key1']); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}, {value: 'oldValue', label: 'Neos.Neos.Ui:Main:invalidValue: "oldValue"', icon: 'exclamation-triangle'}]); | ||
}); | ||
|
||
it('creates missing options for unmatched additional multiple array values', () => { | ||
const processOptions = processSelectBoxOptions( | ||
fakeI18NRegistry, | ||
[{value: 'key1', label: 'Key 1'}, {value: 'key2', label: 'Key 2'}, {value: 'key3', label: 'Key 3'}], | ||
['oldValue', 'key1', 'oldValue2'] | ||
); | ||
|
||
expect(processOptions).toEqual([ | ||
{value: 'key1', label: 'Key 1'}, | ||
{value: 'key2', label: 'Key 2'}, | ||
{value: 'key3', label: 'Key 3'}, | ||
{value: 'oldValue', label: 'Neos.Neos.Ui:Main:invalidValue: "oldValue"', icon: 'exclamation-triangle'}, | ||
{value: 'oldValue2', label: 'Neos.Neos.Ui:Main:invalidValue: "oldValue2"', icon: 'exclamation-triangle'} | ||
]); | ||
}); | ||
|
||
it('ignored current value being empty and dont create missing option', () => { | ||
let processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'} | ||
}, null); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
|
||
processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'} | ||
}, undefined); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
|
||
processOptions = processSelectBoxOptions(fakeI18NRegistry, { | ||
'key1': {label: 'Key 1'} | ||
}, ''); | ||
|
||
expect(processOptions).toEqual([{value: 'key1', label: 'Key 1'}]); | ||
}); | ||
}); |
51 changes: 51 additions & 0 deletions
51
packages/neos-ui-editors/src/Editors/SelectBox/selectBoxHelpers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {I18nRegistry} from '@neos-project/neos-ts-interfaces'; | ||
import {isNil} from '@neos-project/utils-helpers'; | ||
|
||
type RawSelectBoxOptions = {value: string, icon?: string; disabled?: boolean; label: string;}[]|{[key: string]: {icon?: string; disabled?: boolean; label: string;}}; | ||
|
||
type SelectBoxOptions = {value: string, icon?: string; disabled?: boolean; label: string;}[]; | ||
|
||
export const shouldDisplaySearchBox = (options: any, processedSelectBoxOptions: SelectBoxOptions) => options.minimumResultsForSearch >= 0 && processedSelectBoxOptions.length >= options.minimumResultsForSearch; | ||
|
||
// Currently, we're doing an extremely simple lowercase substring matching; of course this could be improved a lot! | ||
export const searchOptions = (searchTerm: string, processedSelectBoxOptions: SelectBoxOptions) => | ||
processedSelectBoxOptions.filter(option => option.label && option.label.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1); | ||
|
||
export const processSelectBoxOptions = (i18nRegistry: I18nRegistry, selectBoxOptions: RawSelectBoxOptions, currentValue: unknown): SelectBoxOptions => { | ||
const validValues: Record<string, true> = {}; | ||
const processedSelectBoxOptions = []; | ||
for (const [key, selectBoxOption] of Object.entries(selectBoxOptions)) { | ||
if (!selectBoxOption || !selectBoxOption.label) { | ||
continue; | ||
} | ||
|
||
const processedSelectBoxOption = { | ||
value: key, | ||
...selectBoxOption, // a value in here overrules value based on the key above. | ||
label: i18nRegistry.translate(selectBoxOption.label) | ||
}; | ||
|
||
validValues[processedSelectBoxOption.value] = true; | ||
processedSelectBoxOptions.push(processedSelectBoxOption); | ||
} | ||
|
||
const valueIsEmpty = isNil(currentValue) || currentValue === ''; | ||
if (valueIsEmpty) { | ||
return processedSelectBoxOptions; | ||
} | ||
|
||
for (const singleValue of Array.isArray(currentValue) ? currentValue : [currentValue]) { | ||
if (singleValue in validValues) { | ||
continue; | ||
} | ||
|
||
// Mismatch detected. Thus we add an option to the schema so the value is displayable: https://github.com/neos/neos-ui/issues/3520 | ||
processedSelectBoxOptions.push({ | ||
value: singleValue, | ||
label: `${i18nRegistry.translate('Neos.Neos.Ui:Main:invalidValue')}: "${singleValue}"`, | ||
icon: 'exclamation-triangle' | ||
}); | ||
} | ||
|
||
return processedSelectBoxOptions; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters