Skip to content

Commit

Permalink
fix: add forwardRef to ProjectSelect component (#6674)
Browse files Browse the repository at this point in the history
Make the tooltip for project selection in the playground work properly
again. Right now, it doesn't work due to an error in react refs.

Because we wrap this in a tooltip in the Playground, we need to forward
the ref to the underlying component.

This follows the steps outlined in
https://mui.com/material-ui/guides/composition/#caveat-with-refs
  • Loading branch information
thomasheartman committed Mar 25, 2024
1 parent 8a9d013 commit 6025ad0
Showing 1 changed file with 80 additions and 72 deletions.
152 changes: 80 additions & 72 deletions frontend/src/component/common/ProjectSelect/ProjectSelect.tsx
@@ -1,4 +1,10 @@
import type { ComponentProps, Dispatch, SetStateAction, VFC } from 'react';
import {
forwardRef,
type ComponentProps,
type Dispatch,
type SetStateAction,
type VFC,
} from 'react';
import { Autocomplete, type SxProps, TextField } from '@mui/material';
import { renderOption } from 'component/playground/Playground/PlaygroundForm/renderOption';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
Expand Down Expand Up @@ -30,85 +36,87 @@ function findAllIndexes(arr: string[], name: string): number[] {
return indexes;
}

export const ProjectSelect: VFC<IProjectSelectProps> = ({
selectedProjects,
onChange,
dataTestId,
sx,
disabled,
}) => {
const { projects: availableProjects } = useProjects();
export const ProjectSelect: VFC<IProjectSelectProps> = forwardRef(
(
{ selectedProjects, onChange, dataTestId, sx, disabled, ...props },
ref,
) => {
const { projects: availableProjects } = useProjects();

const projectNames = availableProjects.map(({ name }) => name);
const projectNames = availableProjects.map(({ name }) => name);

const projectsOptions = [
allOption,
...availableProjects.map(({ name, id }) => {
const indexes = findAllIndexes(projectNames, name);
const isDuplicate = indexes.length > 1;
const projectsOptions = [
allOption,
...availableProjects.map(({ name, id }) => {
const indexes = findAllIndexes(projectNames, name);
const isDuplicate = indexes.length > 1;

return {
label: isDuplicate ? `${name} - (${id})` : name,
id,
};
}),
];
return {
label: isDuplicate ? `${name} - (${id})` : name,
id,
};
}),
];

const isAllProjects =
selectedProjects &&
(selectedProjects.length === 0 ||
(selectedProjects.length === 1 && selectedProjects[0] === '*'));
const isAllProjects =
selectedProjects &&
(selectedProjects.length === 0 ||
(selectedProjects.length === 1 && selectedProjects[0] === '*'));

const onProjectsChange: ComponentProps<typeof Autocomplete>['onChange'] = (
event,
value,
reason,
) => {
const newProjects = value as IOption | IOption[];
if (reason === 'clear' || newProjects === null) {
return onChange([allOption.id]);
}
if (Array.isArray(newProjects)) {
if (newProjects.length === 0) {
const onProjectsChange: ComponentProps<
typeof Autocomplete
>['onChange'] = (event, value, reason) => {
const newProjects = value as IOption | IOption[];
if (reason === 'clear' || newProjects === null) {
return onChange([allOption.id]);
}
if (
newProjects.find(({ id }) => id === allOption.id) !== undefined
) {
if (Array.isArray(newProjects)) {
if (newProjects.length === 0) {
return onChange([allOption.id]);
}
if (
newProjects.find(({ id }) => id === allOption.id) !==
undefined
) {
return onChange([allOption.id]);
}
return onChange(newProjects.map(({ id }) => id));
}
if (newProjects.id === allOption.id) {
return onChange([allOption.id]);
}
return onChange(newProjects.map(({ id }) => id));
}
if (newProjects.id === allOption.id) {
return onChange([allOption.id]);
}

return onChange([newProjects.id]);
};
return onChange([newProjects.id]);
};

return (
<Autocomplete
disablePortal
id='projects'
limitTags={3}
multiple={!isAllProjects}
options={projectsOptions}
sx={sx}
renderInput={(params) => <TextField {...params} label='Projects' />}
renderOption={renderOption}
getOptionLabel={({ label }) => label}
disableCloseOnSelect
size='small'
disabled={disabled}
value={
isAllProjects
? allOption
: projectsOptions.filter(({ id }) =>
selectedProjects.includes(id),
)
}
onChange={onProjectsChange}
data-testid={dataTestId ? dataTestId : 'PROJECT_SELECT'}
/>
);
};
return (
<Autocomplete
{...props}
ref={ref}
disablePortal
id='projects'
limitTags={3}
multiple={!isAllProjects}
options={projectsOptions}
sx={sx}
renderInput={(params) => (
<TextField {...params} label='Projects' />
)}
renderOption={renderOption}
getOptionLabel={({ label }) => label}
disableCloseOnSelect
size='small'
disabled={disabled}
value={
isAllProjects
? allOption
: projectsOptions.filter(({ id }) =>
selectedProjects.includes(id),
)
}
onChange={onProjectsChange}
data-testid={dataTestId ? dataTestId : 'PROJECT_SELECT'}
/>
);
},
);

0 comments on commit 6025ad0

Please sign in to comment.