From 36aad2556ec5cda86f9647f74c4e14b17a18dfb0 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Thu, 22 Jan 2026 12:33:36 +0100 Subject: [PATCH] Group playground context fields into global / project (#11244) Groups project fields in the playground context selector the same way as in the constraint editor. Uses a similar grouping mechanism as in the editable constraint, but simplifies it because there is no need to handle the "current context field", as this is not an editing operation. Also sorts the data by sortOrder. Updates the playground component by using the shared general select component instead of a custom impl. image --- .../PlaygroundCodeFieldset.tsx | 114 ++++++++++++------ 1 file changed, 79 insertions(+), 35 deletions(-) diff --git a/frontend/src/component/playground/Playground/PlaygroundForm/PlaygroundCodeFieldset/PlaygroundCodeFieldset.tsx b/frontend/src/component/playground/Playground/PlaygroundForm/PlaygroundCodeFieldset/PlaygroundCodeFieldset.tsx index 320e52b6c2..f22895dbf0 100644 --- a/frontend/src/component/playground/Playground/PlaygroundForm/PlaygroundCodeFieldset/PlaygroundCodeFieldset.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundForm/PlaygroundCodeFieldset/PlaygroundCodeFieldset.tsx @@ -1,24 +1,19 @@ import { type Dispatch, + type FC, type FormEvent, type SetStateAction, useEffect, useMemo, useState, - type VFC, } from 'react'; import { Box, Button, - FormControl, - InputLabel, - MenuItem, - Select, TextField, Typography, useTheme, Autocomplete, - type SelectChangeEvent, Checkbox, } from '@mui/material'; @@ -34,23 +29,81 @@ import { import CheckBoxOutlineBlank from '@mui/icons-material/CheckBoxOutlineBlank'; import CheckBoxIcon from '@mui/icons-material/CheckBox'; import { useFullUnleashContext } from 'hooks/api/getters/useUnleashContext/useFullUnleashContext.ts'; +import { useUiFlag } from 'hooks/useUiFlag.ts'; +import type { IUnleashContextDefinition } from 'interfaces/context.ts'; +import type { + ISelectOption, + SelectOptionGroup, +} from 'component/common/GeneralSelect/GeneralSelect.tsx'; +import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect.tsx'; interface IPlaygroundCodeFieldsetProps { context: string | undefined; setContext: Dispatch>; } -export const PlaygroundCodeFieldset: VFC = ({ +const createContextFieldOptions = ( + context: IUnleashContextDefinition[], + { groupOptions }: { groupOptions: boolean }, +): ISelectOption[] | SelectOptionGroup[] => { + const optList = (opts: { name: string; sortOrder: number }[]) => + opts + .toSorted((a, b) => a.sortOrder - b.sortOrder) + .map((option) => ({ + key: option.name, + label: option.name, + })); + + if (!groupOptions) { + return optList(context); + } + + const fields = context.reduce( + ({ project, global }, next) => { + if (next.project) { + project.push(next); + } else { + global.push(next); + } + return { project: project, global: global }; + }, + { + project: [] as IUnleashContextDefinition[], + global: [] as IUnleashContextDefinition[], + }, + ); + + const groups: SelectOptionGroup[] = []; + + if (fields.project.length) { + groups.push({ + groupHeader: 'Project context fields', + options: optList(fields.project), + }); + } + if (fields.global.length) { + groups.push({ + groupHeader: 'Global context fields', + options: optList(fields.global), + }); + } + + return groups; +}; + +export const PlaygroundCodeFieldset: FC = ({ context, setContext, }) => { const theme = useTheme(); - const { setToastData } = useToast(); const { context: contextData } = useFullUnleashContext(); - const contextOptions = contextData - .sort((a, b) => a.sortOrder - b.sortOrder) - .map(({ name }) => name); + + const groupOptions = useUiFlag('projectContextFields'); + const contextOptions = createContextFieldOptions(contextData, { + groupOptions, + }); + const [error, setError] = useState(); const [fieldExist, setFieldExist] = useState(false); const [contextField, setContextField] = useState(''); @@ -237,10 +290,10 @@ export const PlaygroundCodeFieldset: VFC = ({ ); }; - const changeContextField = (event: SelectChangeEvent) => { - setContextField(event.target.value || ''); + const changeContextField = (value: string) => { + setContextField(value || ''); - if (event.target.value === 'currentTime') { + if (value === 'currentTime') { return setContextValue(new Date().toISOString()); } @@ -260,27 +313,18 @@ export const PlaygroundCodeFieldset: VFC = ({ - - - Context field - - - + + {resolveInput()}