Skip to content

feat: StudioCodeListEditor - display Numberfield or Checkbox based on value type #14398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e9b29b2
feat: Add text resource selector to code list editor
TomasEng Jan 3, 2025
d6c13ac
Merge remote-tracking branch 'origin' into add-numberfield-to-code-li…
ErlingHauan Jan 9, 2025
e32b242
add conditional rendering of numberfield
ErlingHauan Jan 9, 2025
e861d29
base new code list item value type on first item in codelist
ErlingHauan Jan 9, 2025
50ea9e5
Merge remote-tracking branch 'origin' into add-numberfield-to-code-li…
ErlingHauan Jan 10, 2025
9e9a73f
renames
ErlingHauan Jan 10, 2025
29079f6
update test name
ErlingHauan Jan 10, 2025
fd25884
Merge main to branch
ErlingHauan Jan 17, 2025
1724951
Merge remote-tracking branch 'origin' into add-numberfield-to-code-li…
ErlingHauan Jan 20, 2025
aa6c8d2
Render checkbox when value is boolean
ErlingHauan Jan 20, 2025
3aed7a8
Render checkbox when value is boolean
ErlingHauan Jan 20, 2025
0882627
split input components
ErlingHauan Jan 20, 2025
8c3861d
Merge branch 'add-numberfield-to-code-list-editor' of https://github.…
ErlingHauan Jan 20, 2025
80fdc7f
base type of new row on last row
ErlingHauan Jan 20, 2025
e5194f8
Forward ref to input cells
ErlingHauan Jan 21, 2025
0bd270e
Add tests
ErlingHauan Jan 21, 2025
954bbbc
Update tests
ErlingHauan Jan 22, 2025
cf17f0b
Merge branch 'main' into add-numberfield-to-code-list-editor
ErlingHauan Jan 22, 2025
0e73d8e
Update tests
ErlingHauan Jan 22, 2025
1d01ce3
Use correct type and refactoring
ErlingHauan Jan 22, 2025
3f0cdc3
Use type assertion in getTypeOfLastValue
ErlingHauan Jan 22, 2025
4f1c8ba
Implement suggestions from rabbit
ErlingHauan Jan 22, 2025
6c4ad49
Replace isNan with undefined check
ErlingHauan Jan 22, 2025
267d8de
Partly fix PR comments
ErlingHauan Jan 24, 2025
2ece2f2
Add additional validations
ErlingHauan Jan 27, 2025
c1aede4
add validation when a code list has multiple different types
ErlingHauan Jan 30, 2025
69dad58
update tests for findCodeListErrors
ErlingHauan Feb 4, 2025
a97dbd4
add isFieldValid utility function
ErlingHauan Feb 4, 2025
2e75731
render Numberfield for undefined values, and add texts for error mult…
ErlingHauan Feb 6, 2025
dc76955
fix type errors
ErlingHauan Feb 6, 2025
d9b82ad
rename textkeys, so that they are easier to compare in nb.json
ErlingHauan Feb 6, 2025
b57d41d
fix tests
ErlingHauan Feb 6, 2025
8ca7808
remove text beside checkbox
ErlingHauan Feb 6, 2025
a7398f2
make TypedInputCellProps generic
ErlingHauan Feb 10, 2025
bb44d31
use rest prop in TypedInputCell
ErlingHauan Feb 10, 2025
5745260
add undefined as type parameter for NumberfieldCell
ErlingHauan Feb 10, 2025
adae170
rename hasSingleType in describe string
ErlingHauan Feb 10, 2025
6168338
strengthen extractUniqueTypes test
ErlingHauan Feb 10, 2025
c156e3e
Merge branch 'add-numberfield-to-code-list-editor' of https://github.…
ErlingHauan Feb 10, 2025
d8cac28
Merge branch 'main' into add-numberfield-to-code-list-editor
ErlingHauan Feb 10, 2025
f26f5be
Add rest parameter to Numberfield, CheckboxFiel and Textfield
ErlingHauan Feb 10, 2025
07ade2a
Add test for error in getTypeOfLastValue
ErlingHauan Feb 10, 2025
98f0a8c
Merge branch 'main' into add-numberfield-to-code-list-editor
TomasEng Feb 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { CodeListItem } from './types/CodeListItem';
import { StudioButton } from '../StudioButton';
import {
removeCodeListItem,
addEmptyCodeListItem,
addNewCodeListItem,
changeCodeListItem,
isCodeListEmpty,
} from './utils';
Expand Down Expand Up @@ -110,7 +110,7 @@ function ControlledCodeListEditor({
const errorMap = useMemo<ValueErrorMap>(() => findCodeListErrors(codeList), [codeList]);

const handleAddButtonClick = useCallback(() => {
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
onChange(updatedCodeList);
onAddOrDeleteItem?.(updatedCodeList);
}, [codeList, onChange, onAddOrDeleteItem]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function StudioCodeListEditorRow({
);
}

type InputCellProps = {
type TypedInputCellProps = {
value: CodeListItemValue;
label: string;
onChange: (newValue: CodeListItemValue) => void;
Expand All @@ -114,7 +114,7 @@ type InputCellProps = {
error?: string;
};

function TypedInputCell({ error, label, value, onChange, autoComplete }: InputCellProps) {
function TypedInputCell({ error, label, value, onChange, autoComplete }: TypedInputCellProps) {
const ref = useRef<HTMLInputElement>(null);

useEffect((): void => {
Expand All @@ -125,45 +125,43 @@ function TypedInputCell({ error, label, value, onChange, autoComplete }: InputCe
event.target.reportValidity();
}, []);

const shouldRenderNumberfield = typeof value === 'number';
const shouldRenderCheckbox = typeof value === 'boolean';

if (shouldRenderNumberfield) {
return (
<NumberfieldCell
label={label}
value={value}
autoComplete={autoComplete}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
} else if (shouldRenderCheckbox) {
return (
<CheckboxCell
label={label}
value={value}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
} else {
return (
<TextfieldCell
label={label}
value={value}
autoComplete={autoComplete}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
switch (typeof value) {
case 'number':
return (
<NumberfieldCell
label={label}
value={value}
autoComplete={autoComplete}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
case 'boolean':
return (
<CheckboxCell
label={label}
value={value}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
default:
return (
<TextfieldCell
label={label}
value={value}
autoComplete={autoComplete}
onChange={onChange}
onFocus={handleFocus}
ref={ref}
/>
);
}
}

const NumberfieldCell = forwardRef<HTMLInputElement, InputCellProps>(
const NumberfieldCell = forwardRef<HTMLInputElement, TypedInputCellProps>(
({ label, value, onChange, onFocus, autoComplete }, ref) => {
const handleNumberChange = useCallback(
(numberValue: number): void => {
Expand All @@ -189,7 +187,7 @@ const NumberfieldCell = forwardRef<HTMLInputElement, InputCellProps>(

NumberfieldCell.displayName = 'NumberfieldCell';

const CheckboxCell = forwardRef<HTMLInputElement, InputCellProps>(
const CheckboxCell = forwardRef<HTMLInputElement, TypedInputCellProps>(
({ label, value, onChange, onFocus }, ref) => {
const handleBooleanChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>): void => {
Expand All @@ -215,7 +213,7 @@ const CheckboxCell = forwardRef<HTMLInputElement, InputCellProps>(

CheckboxCell.displayName = 'CheckboxCell';

const TextfieldCell = forwardRef<HTMLInputElement, InputCellProps>(
const TextfieldCell = forwardRef<HTMLInputElement, TypedInputCellProps>(
({ label, value, onChange, onFocus, autoComplete }, ref) => {
const handleTextChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>): void => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type TypeofResult =
| 'string'
| 'number'
| 'bigint'
| 'boolean'
| 'symbol'
| 'undefined'
| 'object'
| 'function';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CodeList } from './types/CodeList';
import {
addEmptyCodeListItem,
addNewCodeListItem,
changeCodeListItem,
emptyBooleanItem,
emptyNumberItem,
Expand Down Expand Up @@ -29,7 +29,7 @@ describe('StudioCodelistEditor utils', () => {
describe('addEmptyCodeListItem', () => {
it('Adds an empty string item when the code list is empty', () => {
const codeList: CodeList = [];
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
expect(updatedCodeList).toEqual([...codeList, emptyStringItem]);
});

Expand All @@ -38,7 +38,7 @@ describe('StudioCodelistEditor utils', () => {
{ value: 1, label: 'numberItem' },
{ value: 'two', label: 'stringItem' },
];
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
expect(updatedCodeList).toEqual([...codeList, emptyStringItem]);
});

Expand All @@ -47,7 +47,7 @@ describe('StudioCodelistEditor utils', () => {
{ value: 'one', label: 'stringItem' },
{ value: 2, label: 'numberItem' },
];
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
expect(updatedCodeList).toEqual([...codeList, emptyNumberItem]);
});

Expand All @@ -56,13 +56,13 @@ describe('StudioCodelistEditor utils', () => {
{ value: 0, label: 'numberItem' },
{ value: true, label: 'booleanItem' },
];
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
expect(updatedCodeList).toEqual([...codeList, emptyBooleanItem]);
});

it('Returns a new instance', () => {
const codeList = createTestCodeList();
const updatedCodeList = addEmptyCodeListItem(codeList);
const updatedCodeList = addNewCodeListItem(codeList);
expect(updatedCodeList).not.toBe(codeList);
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { CodeListItem } from './types/CodeListItem';
import type { CodeList } from './types/CodeList';
import type { TypeofResult } from './types/TypeofResult';
import { ArrayUtils } from '@studio/pure-functions';

export const emptyStringItem: CodeListItem = {
Expand All @@ -17,12 +18,12 @@ export const emptyBooleanItem: CodeListItem = {
label: '',
};

export function addEmptyCodeListItem(codeList: CodeList): CodeList {
const emptyItem: CodeListItem = getEmptyItem(codeList);
return addCodeListItem(codeList, emptyItem);
export function addNewCodeListItem(codeList: CodeList): CodeList {
const newEmptyItem: CodeListItem = getNewEmptyItem(codeList);
return addCodeListItem(codeList, newEmptyItem);
}

function getEmptyItem(codeList: CodeList): CodeListItem {
function getNewEmptyItem(codeList: CodeList): CodeListItem {
if (codeList.length === 0) return emptyStringItem;

switch (getTypeOfLastValue(codeList)) {
Expand All @@ -35,9 +36,9 @@ function getEmptyItem(codeList: CodeList): CodeListItem {
}
}

function getTypeOfLastValue(codeList: CodeList) {
function getTypeOfLastValue(codeList: CodeList): TypeofResult {
const lastCodeListItem = codeList[codeList.length - 1];
return typeof lastCodeListItem.value as 'string' | 'number' | 'boolean';
return typeof lastCodeListItem.value;
}

function addCodeListItem(codeList: CodeList, item: CodeListItem): CodeList {
Expand Down
Loading